HIGH sql injectiongorilla muxjwt tokens

Sql Injection in Gorilla Mux with Jwt Tokens

Sql Injection in Gorilla Mux with Jwt Tokens — how this specific combination creates or exposes the vulnerability

SQL injection in a Gorilla Mux application that uses JWT tokens occurs when user-controlled data from the request is concatenated into SQL queries without proper parameterization, even though authentication is mediated by JWTs. The presence of JWT tokens does not prevent SQL injection; it only indicates the caller is authenticated. If a token is accepted but the handler builds queries by string interpolation, the authentication boundary is bypassed from the perspective of the API because the token is trusted but the input is not.

In practice, this often maps to the Authentication and Input Validation checks in middleBrick’s scan. For example, an endpoint like /users/{userID} authenticated via JWT may still execute SELECT * FROM users WHERE id = '" + userID + "'. An attacker who possesses a valid JWT (stolen or obtained via account takeover) can still inject SQL through userID. Because the router does not enforce strict input validation, the malicious payload is passed to the database, leading to unauthorized data access or modification. MiddleBrick’s unauthenticated attack surface testing treats the endpoint as unauthenticated for injection tests, exposing how input handling—not token presence—drives the risk.

Specific OWASP API Top 10 categories relevant here include Broken Object Level Authorization (BOLA/IDOR) when combined with injection, and Input Validation weaknesses. A real-world pattern is using string concatenation with httprouter path parameters and query parameters without sanitization. For instance, a handler might read r.URL.Query().Get("search") and embed it directly into a LIKE clause. Even with JWT-based middleware verifying identity, the injection remains because the SQL layer receives untrusted data. MiddleBrick’s checks for Property Authorization and Input Validation highlight these gaps by correlating spec definitions with runtime behavior, showing where path parameters, headers, or cookies feed into SQL strings.

Consider a vulnerable pattern: a route registered with router.HandleFunc("/api/profile", getProfile).Methods("GET") and a JWT middleware that sets ctx claims. If getProfile extracts a query parameter like category and builds a query such as "SELECT * FROM profiles WHERE category = '" + category + "'", the JWT token does nothing to neutralize the injection. The router ensures a token is present, but the SQL is still formed by concatenation. This is where middleBrick’s cross-referencing of OpenAPI specs and runtime findings can identify mismatches between declared authentication and actual input handling.

Real attack patterns include classic techniques like ' OR 1=1 -- to bypass filters, or stacked queries if the driver permits. Injection can also lead to exposure of sensitive data, aligning with Data Exposure findings in scans. Because JWT tokens are often issued with broad scopes, the blast radius of a successful injection is larger. MiddleBrick’s LLM/AI Security checks do not apply here, but the scanner’s Authentication and Input Validation components will flag the lack of parameterized queries and insufficient authorization checks at the property level.

Jwt Tokens-Specific Remediation in Gorilla Mux — concrete code fixes

Remediation centers on strict input validation and parameterized SQL, independent of JWT handling. JWT middleware should remain focused on identity verification, while data access layers must treat all user-supplied values as untrusted. The following examples show correct patterns for Gorilla Mux with JWT tokens.

Example 1: Safe query with path parameter and JWT middleware

package main

import (
    "database/sql"
    "net/http"
    "github.com/gorilla/mux"
    _ "github.com/lib/pq"
)

func getProfile(db *sql.DB) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        userID := vars["userID"]
        // Use parameterized query; do not concatenate userID
        row := db.QueryRow("SELECT id, email, name FROM users WHERE id = $1", userID)
        var id int
        var email, name string
        if err := row.Scan(&id, &email, &name); err != nil {
            http.Error(w, "not found", http.StatusNotFound)
            return
        }
        w.Write([]byte(email))
    }
}

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        tokenString := r.Header.Get("Authorization")
        // Verify JWT token and set claims in context
        claims, err := verifyToken(tokenString)
        if err != nil {
            http.Error(w, "unauthorized", http.StatusUnauthorized)
            return
        }
        ctx := context.WithValue(r.Context(), "claims", claims)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

func main() {
    db, _ := sql.Open("postgres", "connstr")
    r := mux.NewRouter()
    r.HandleFunc("/api/profile/{userID}", getProfile(db)).Methods("GET")
    r.Use(authMiddleware)
    http.ListenAndServe(":8080", r)
}

Example 2: Safe query with query parameters and prepared statements

func searchProfiles(db *sql.DB) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        category := r.URL.Query().Get("category")
        // Validate category against an allowlist or regex
        if category == "" || !isValidCategory(category) {
            http.Error(w, "bad request", http.StatusBadRequest)
            return
        }
        stmt, err := db.Prepare("SELECT id, name FROM profiles WHERE category = $1")
        if err != nil {
            http.Error(w, "server error", http.StatusInternalServerError)
            return
        }
        defer stmt.Close()
        rows, err := stmt.Query(category)
        if err != nil {
            http.Error(w, "server error", http.StatusInternalServerError)
            return
        }
        defer rows.Close()
        for rows.Next() {
            var id int
            var name string
            rows.Scan(&id, &name)
            w.Write([]byte(name + ","))
        }
    }
}

func isValidCategory(cat string) bool {
    // Example allowlist
    allowed := map[string]bool{"tech": true, "health": true, "finance": true}
    return allowed[cat]
}

Key practices: always use $1, $2 placeholders (PostgreSQL) or ? (other drivers) with db.Query or db.Exec; avoid fmt.Sprintf or string concatenation for SQL; validate path and query parameters against allowlists or strict regex; keep JWT verification separate from data access logic; ensure that claims from the token are not used to dynamically build SQL without validation. MiddleBrick’s scans can verify these patterns by checking that endpoints with authentication also enforce input validation and parameterized queries.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does a valid JWT token prevent SQL injection in Gorilla Mux endpoints?
No. JWT tokens confirm identity but do not sanitize input. SQL injection depends on how query strings are built; concatenating user-controlled values—even from authenticated requests—remains dangerous. Use parameterized queries and validate inputs independently.
How does middleBrick detect SQL injection risks in authenticated endpoints?
middleBrick tests the unauthenticated attack surface and can correlate path parameters, query parameters, and headers with SQL-related findings. It flags endpoints that accept user input without parameterized queries, regardless of whether JWT middleware is present, highlighting mismatches between authentication declarations and input validation.