Spaces:
Sleeping
Sleeping
| 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)) | |
| } |