Sql Injection in Chi with Basic Auth
Sql Injection in Chi with Basic Auth — how this specific combination creates or exposes the vulnerability
SQL injection remains a critical risk in web services, and combining it with HTTP Basic Authentication in Chi can amplify exposure when authentication data and SQL logic are mishandled. Chi is a lightweight routing library for Go that does not inherently protect against injection; it relies on the developer to use safe practices when constructing queries. When Basic Auth is used, credentials are typically extracted from the Authorization header, decoded, and passed into business logic. If these values are then concatenated into SQL strings, the stage is set for injection.
Consider a handler that reads username and password from Basic Auth and uses them directly in a query:
package main
import (
"database/sql"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
_ "github.com/lib/pq"
)
func unsafeLogin(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Vulnerable: string concatenation with user input
query := "SELECT id, role FROM users WHERE username = '" + user + "' AND password = '" + pass + "'"
var id int
var role string
err := db.QueryRow(query).Scan(&id, &role)
if err != nil {
http.Error(w, "Internal error", http.StatusInternalServerError)
return
}
w.Write([]byte("OK"))
}
}
In this pattern, the user and pass values from r.BasicAuth() are interpolated directly into the SQL string. An attacker who knows the endpoint exists can supply crafted credentials such as admin' -- as the username and anything as the password, altering the SQL logic to bypass authentication. Because the scan endpoint is unauthenticated, middleBrick’s checks for Authentication and Input Validation can flag this as a high-severity SQL injection risk. The presence of Basic Auth does not reduce the severity; it simply means that leaked credentials or weak password policies can compound the impact if the SQL layer is also vulnerable.
Additionally, Basic Auth sends credentials in base64 encoding, not encryption. If the request traverses an untrusted network without TLS, credentials are easily decoded. middleBrick’s Encryption check would highlight this in-transit exposure, while the SQL injection findings emphasize how unchecked input leads to unauthorized data access. Even when authentication succeeds, unsafe query construction can allow privilege escalation, aligning with BOLA/IDOR and BFLA/Privilege Escalation checks when user-specific data is accessed without proper authorization checks.
Basic Auth-Specific Remediation in Chi — concrete code fixes
Remediation centers on never interpolating user-controlled values into SQL and instead using parameterized queries or prepared statements. Authentication logic should validate credentials against a parameterized query or a secure store, and middleware should enforce authentication before handlers execute.
Here is a safe approach using parameterized queries with PostgreSQL:
package main
import (
"database/sql"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
_ "github.com/lib/pq"
)
func safeLogin(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Safe: parameterized query
var id int
var role string
err := db.QueryRow("SELECT id, role FROM users WHERE username = $1 AND password = $2", user, pass).Scan(&id, ¤tRole)
if err != nil {
if err == sql.ErrNoRows {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
http.Error(w, "Internal error", http.StatusInternalServerError)
return
}
// Optionally set a session or context for downstream authorization
ctx := context.WithValue(r.Context(), "userID", id)
r = r.WithContext(ctx)
w.Write([]byte("OK"))
}
}
In this version, $1 and $2 placeholders ensure that user and pass are sent separately from the SQL command, preventing injection. You can further harden the service by adding Chi middleware for authentication, so each request is validated before reaching handlers:
func basicAuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok || !isValid(user, pass) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(basicAuthMiddleware)
r.Get("/secure", secureHandler)
http.ListenAndServe(":8080", r)
}
Use environment variables or a secrets manager for credentials rather than storing them in code or logs. middleBrick’s Authentication and Input Validation checks can verify that your endpoints require authentication and that inputs are properly parameterized, while the GitHub Action can enforce these rules in CI/CD by failing builds if unsafe patterns are detected.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |