File size: 4,632 Bytes
7dccad9
 
 
 
 
12a70ac
7dccad9
 
 
12a70ac
7dccad9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12a70ac
 
 
 
 
 
 
 
 
 
 
 
7dccad9
 
 
 
 
12a70ac
7dccad9
 
12a70ac
 
 
 
 
7dccad9
 
12a70ac
 
7dccad9
 
12a70ac
 
7dccad9
12a70ac
7dccad9
12a70ac
 
 
 
 
7dccad9
 
 
 
 
 
 
 
12a70ac
7dccad9
 
 
 
 
 
 
 
 
0399646
12a70ac
 
 
 
 
 
0399646
12a70ac
 
 
 
 
 
 
 
 
 
7dccad9
 
 
 
 
 
 
 
0399646
7dccad9
 
 
 
 
0399646
7dccad9
 
 
 
 
12a70ac
7dccad9
 
 
 
 
 
0399646
7dccad9
 
12a70ac
 
 
7dccad9
 
 
 
 
 
 
 
 
 
12a70ac
7dccad9
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main

import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"

	_ "github.com/lib/pq"
)

type User struct {
	ID       int
	Username string
	Flag     string
}

func connectDB() (*sql.DB, error) {
	connStr := os.Getenv("DATABASE_URL")
	if connStr == "" {
		return nil, fmt.Errorf("DATABASE_URL environment variable is not set")
	}
	return sql.Open("postgres", connStr)
}

func main() {
	// 1. Endpoint to View Source Code (Crucial for the CTF)
	http.HandleFunc("/source", func(w http.ResponseWriter, r *http.Request) {
		content, err := ioutil.ReadFile("main.go")
		if err != nil {
			http.Error(w, "Could not read source code.", http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain")
		w.Write(content)
	})

	// 2. Login Page
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		html := `
		<!DOCTYPE html>
		<html>
		<head>
			<title>Secure Login System v2.0</title>
			<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
		</head>
		<body class="bg-gray-900 text-white flex flex-col items-center justify-center h-screen">
			<div class="bg-gray-800 p-8 rounded shadow-lg w-96 border-t-4 border-blue-500">
				<h1 class="text-2xl mb-2 text-center font-bold text-blue-400">SECURE GATEWAY</h1>
				<p class="text-gray-400 mb-6 text-center text-xs">Protected by GoWAF™ technology</p>
				
				<form action="/login" method="POST" class="space-y-4">
					<div>
						<label class="block text-sm font-medium text-gray-300">Username</label>
						<input type="text" name="username" class="w-full p-2 bg-gray-700 rounded border border-gray-600 focus:border-blue-500 outline-none" placeholder="Enter username">
					</div>
					<div>
						<label class="block text-sm font-medium text-gray-300">Password</label>
						<input type="password" name="password" class="w-full p-2 bg-gray-700 rounded border border-gray-600 focus:border-blue-500 outline-none" placeholder="••••••">
					</div>
					<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded transition">AUTHENTICATE</button>
				</form>
				
				<div class="mt-6 border-t border-gray-700 pt-4 text-center">
					<p class="text-xs text-gray-500">Developers only:</p>
					<a href="/source" class="text-sm text-blue-400 hover:underline">View Source Code</a>
				</div>
			</div>
		</body>
		</html>
		`
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(html))
	})

	// 3. The Hardened (but still vulnerable) Login Endpoint
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		username := r.FormValue("username")
		password := r.FormValue("password")

		
		ua := r.Header.Get("User-Agent")
		if ua != "Secure-CTF-Browser/1.0" {
			http.Error(w, "Security Alert: Browser not authorized. Please use 'Secure-CTF-Browser/1.0'", http.StatusForbidden)
			return
		}

		
		if username == "admin" {
			http.Error(w, "Direct login as 'admin' is disabled for security reasons.", http.StatusForbidden)
			return
		}

		if strings.Contains(username, " ") || strings.Contains(password, " ") {
			http.Error(w, "WAF Detection: Spaces are not allowed in input fields.", http.StatusBadRequest)
			return
		}

		db, err := connectDB()
		if err != nil {
			http.Error(w, "Database connection failed", http.StatusInternalServerError)
			log.Println("DB Error:", err)
			return
		}
		defer db.Close()

		
		query := fmt.Sprintf("SELECT id, username, flag FROM users WHERE username = '%s' AND password = '%s'", username, password)
		
		log.Printf("Executing Query: %s\n", query)

		var user User
		
		err = db.QueryRow(query).Scan(&user.ID, &user.Username, &user.Flag)

		if err != nil {
			if err == sql.ErrNoRows {
				w.WriteHeader(http.StatusUnauthorized)
				w.Write([]byte("Invalid credentials."))
			} else {
				http.Error(w, "Query error: "+err.Error(), http.StatusInternalServerError)
			}
			return
		}

		
		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, `
			<div style="font-family: monospace; background: #111; color: #4ade80; padding: 20px; text-align: center;">
				<h1>SYSTEM BREACHED</h1>
				<p>User: %s</p>
				<p style="font-size: 24px; border: 1px dashed #4ade80; display: inline-block; padding: 10px;">FLAG: %s</p>
			</div>
		`, user.Username, user.Flag)
	})

	port := os.Getenv("PORT")
	if port == "" {
		port = "7860"
	}

	log.Printf("CTF Hard Mode listening on port %s", port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}