HIGH cache poisoninggorilla mux

Cache Poisoning in Gorilla Mux

How Cache Poisoning Manifests in Gorilla Mux

Cache poisoning in Gorilla Mux occurs when an attacker manipulates HTTP requests to store malicious or incorrect data in the cache, which then gets served to legitimate users. This vulnerability is particularly dangerous in API endpoints that don't properly validate input parameters or fail to normalize request paths.

The most common attack vector involves exploiting Gorilla Mux's path parameter handling. Consider this vulnerable route:

router := mux.NewRouter()
router.HandleFunc("/api/users/{id}", getUserHandler).Methods("GET")

An attacker can craft requests like:

GET /api/users/1
GET /api/users/1/../../etc/passwd
GET /api/users/1?param=%0a%0d

Without proper validation, Gorilla Mux's path parameter extraction can lead to cache poisoning. The router's Vars() function extracts parameters without canonicalizing the path, allowing path traversal attacks to reach the cache layer.

Another attack pattern exploits Gorilla Mux's strict slash handling. By default, mux.Router treats /api/users and /api/users/ as different routes. An attacker can:

GET /api/users?id=1
GET /api/users/?id=1

These requests may produce different cache keys, allowing poisoned responses to persist. The issue compounds when using middleware that caches responses based on request URLs without normalizing them first.

Query parameter manipulation is particularly effective against Gorilla Mux applications. The router's parameter parsing doesn't automatically handle parameter order or duplicate keys:

GET /api/search?q=test&page=2
GET /api/search?page=2&q=test

If your cache key generation is order-sensitive, these become separate cache entries, enabling cache poisoning through parameter manipulation.

Header-based cache poisoning also affects Gorilla Mux applications. The router passes all headers through without validation, so attackers can exploit caching systems that use headers like Accept-Language or User-Agent in their cache keys:

GET /api/data HTTP/1.1
Accept-Language: en; q=0.9, xx; q=0.1
User-Agent: Mozilla/5.0 (poisoned)

Without proper header validation and canonicalization, these requests can poison caches with malicious content that gets served to users with matching headers.

Gorilla Mux-Specific Detection

Detecting cache poisoning in Gorilla Mux applications requires examining both the routing logic and how cache keys are generated. Start by analyzing your route definitions for path parameter vulnerabilities:

router := mux.NewRouter()
router.HandleFunc("/api/users/{id}", getUserHandler)

Run a security scan using middleBrick to identify these patterns automatically. The scanner tests for path traversal attempts, parameter manipulation, and header-based attacks specific to Gorilla Mux's routing behavior.

middleBrick's black-box scanning approach is particularly effective here because it doesn't require access to your source code. It sends crafted requests to your API endpoints and analyzes the responses for cache poisoning indicators:

$ middlebrick scan https://api.example.com
✓ Authentication bypass: PASS
✓ BOLA/IDOR: PASS
⚠️  Cache Poisoning: HIGH RISK
  - Path traversal in route parameters
  - Inconsistent cache key generation
  - Header manipulation possible

The scanner tests 12 security categories in parallel, including specific cache poisoning vectors that exploit Gorilla Mux's path parameter handling and strict slash matching.

For manual detection, examine how your application generates cache keys. Common vulnerabilities include:

// VULNERABLE - order-sensitive
key := fmt.Sprintf("%s:%s", r.URL.Path, r.URL.RawQuery)

// VULNERABLE - header-based poisoning
key := fmt.Sprintf("%s:%s", r.URL.Path, r.Header.Get("Accept-Language"))

// VULNERABLE - no path normalization
key := r.URL.Path // /api/users/1 and /api/users/1/ treated differently

middleBrick's OpenAPI analysis can also detect cache poisoning risks by examining your API specification. It resolves $ref definitions and cross-references them with runtime findings to identify endpoints vulnerable to parameter manipulation.

The scanner specifically tests for Gorilla Mux's path parameter extraction behavior by sending requests with:

  • Path traversal sequences (../, ./)
  • URL-encoded characters
  • Duplicate parameters
  • Parameter order variations
  • Header manipulation attempts

Each test includes severity scoring and remediation guidance specific to the vulnerability pattern discovered.

Gorilla Mux-Specific Remediation

Fixing cache poisoning in Gorilla Mux applications requires both proper request normalization and secure cache key generation. Start by implementing path canonicalization before parameter extraction:

func canonicalizePath(r *http.Request) string {
    // Remove duplicate slashes
    path := strings.ReplaceAll(r.URL.Path, "//", "/")
    
    // Resolve path traversal
    if strings.Contains(path, "/../") || strings.Contains(path, "/./") {
        cleanPath := path.Clean()
        if cleanPath == "." {
            cleanPath = "/"
        }
        return cleanPath
    }
    return path
}

Apply this normalization before your route handlers process the request:

router.Use(func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = canonicalizePath(r)
        next.ServeHTTP(w, r)
    })
})

For parameter handling, validate and sanitize all path parameters immediately after extraction:

func getUserHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id := vars["id"]
    
    // Validate parameter - only allow alphanumeric IDs
    if !regexp.MustCompile(`^[a-zA-Z0-9-]+$`).MatchString(id) {
        http.Error(w, "Invalid ID format", http.StatusBadRequest)
        return
    }
    
    // Continue with safe processing
}

Implement consistent cache key generation that's immune to parameter order and manipulation:

func generateCacheKey(r *http.Request) string {
    // Canonical path
    path := canonicalizePath(r)
    
    // Sort query parameters
    q := r.URL.Query()
    keys := make([]string, 0, len(q))
    for k := range q {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    
    // Build normalized query string
    var buf bytes.Buffer
    for _, k := range keys {
        values := q[k]
        sort.Strings(values)
        for _, v := range values {
            if buf.Len() > 0 {
                buf.WriteByte('&')
            }
            buf.WriteString(url.QueryEscape(k))
            buf.WriteByte('=')
            buf.WriteString(url.QueryEscape(v))
        }
    }
    
    // Combine path and normalized query
    return fmt.Sprintf("%s?%s", path, buf.String())
}

For header-based cache poisoning prevention, whitelist allowed headers and normalize their values:

func sanitizeHeaders(r *http.Request) http.Header {
    allowed := map[string]bool{
        "accept-language": true,
        "user-agent":      true,
    }
    
    sanitized := http.Header{}
    for k, v := range r.Header {
        if allowed[strings.ToLower(k)] {
            sanitized[k] = v
        }
    }
    return sanitized
}

Integrate these protections with your caching middleware:

type secureCacheHandler struct {
    next   http.Handler
    cache  cache.Cache
}

func (sh *secureCacheHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    key := generateCacheKey(r)
    
    if cached, found := sh.cache.Get(key); found {
        w.Write(cached)
        return
    }
    
    // Continue to handler
    rec := httptest.NewRecorder()
    sh.next.ServeHTTP(rec, r)
    
    // Cache only successful responses
    if rec.Code == http.StatusOK {
        sh.cache.Set(key, rec.Body.Bytes(), 300*time.Second)
    }
    
    // Write response
    for k, v := range rec.Header() {
        w.Header()[k] = v
    }
    w.WriteHeader(rec.Code)
    w.Write(rec.Body.Bytes())
}

Frequently Asked Questions

How does Gorilla Mux's path parameter handling contribute to cache poisoning?
Gorilla Mux's Vars() function extracts path parameters without canonicalizing the request path. This means requests like /api/users/1 and /api/users/1/../../etc/passwd can produce different parameter values if not properly validated. The router also treats /api/users and /api/users/ as distinct routes by default, creating multiple cache keys for semantically identical requests.
Can middleBrick detect cache poisoning vulnerabilities in my Gorilla Mux application?
Yes, middleBrick's black-box scanning tests for cache poisoning by sending crafted requests that exploit Gorilla Mux's path parameter handling and cache key generation patterns. It tests for path traversal, parameter manipulation, and header-based attacks without requiring access to your source code. The scanner provides severity scores and specific remediation guidance for any vulnerabilities found.