sql-injection-1 / main.go
lifedebugger's picture
Update main.go
0399646 verified
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))
}