Integer Overflow in Gorilla Mux
How Integer Overflow Manifests in Gorilla Mux
Integer overflow in Gorilla Mux typically occurs when path parameters are parsed as integers without proper bounds checking. Consider a route that extracts a user ID from the URL:
router := mux.NewRouter()
router.HandleFunc("/users/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Use id without checking bounds
user := getUserByID(id) // Potential overflow if id is max int
json.NewEncoder(w).Encode(user)
})
The vulnerability arises when extremely large numeric values are passed as path parameters. If an attacker supplies a value larger than the maximum int size (typically 2^31-1 on 32-bit systems or 2^63-1 on 64-bit), the conversion may wrap around to a negative number or zero due to two's complement arithmetic.
Gorilla Mux's regex-based parameter extraction doesn't validate numeric ranges. An attacker can exploit this by crafting requests like:
GET /users/9999999999999999999999999999999999999999
This value, when converted to an int, may overflow and wrap to a negative number or a small positive integer, potentially allowing access to unauthorized user records or triggering unexpected application behavior.
Another manifestation occurs with pagination parameters. A route like:
router.HandleFunc("/items/{page:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
page, _ := strconv.Atoi(vars["page"])
items := getItems(page)
json.NewEncoder(w).Encode(items)
})
Can be exploited by passing extremely large page numbers that overflow during multiplication operations in the pagination logic, potentially causing the application to return incorrect data or crash.
Gorilla Mux-Specific Detection
Detecting integer overflow vulnerabilities in Gorilla Mux applications requires both static analysis and runtime scanning. The middleBrick API security scanner specifically tests for this issue by:
- Scanning all numeric path parameters extracted by Gorilla Mux's regex patterns
- Testing boundary conditions with extremely large numeric values
- Checking if converted integers are properly validated before use
- Verifying that arithmetic operations on these values don't cause overflows
To manually test for this vulnerability, you can use curl to probe your endpoints:
# Test with extremely large numbers
curl -v "http://localhost:8080/users/999999999999999999999999"
# Test with values near int boundaries
curl -v "http://localhost:8080/items/2147483647" # Max 32-bit int
curl -v "http://localhost:8080/items/2147483648" # Overflow boundary
Look for unexpected behavior such as:
- Successful responses with unexpected data
- Internal server errors (500) that might indicate overflow crashes
- Negative IDs being processed
- Access to records you shouldn't have permission to view
middleBrick's scanning engine automatically identifies these patterns by analyzing your running API endpoints without requiring source code access. It tests the unauthenticated attack surface and reports findings with severity levels and remediation guidance.
Gorilla Mux-Specific Remediation
The most effective remediation for integer overflow in Gorilla Mux is to validate numeric parameters at the router level before they reach your handlers. Here's a robust approach:
package main
import (
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
// Custom integer parameter validation middleware
func validateIntParam(paramName string, minValue, maxValue int) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
if val, exists := vars[paramName]; exists {
intVal, err := strconv.Atoi(val)
if err != nil || intVal < minValue || intVal > maxValue {
http.Error(w, fmt.Sprintf("Invalid %s parameter", paramName), http.StatusBadRequest)
return
}
// Store validated value in request context
ctx := r.Context()
ctx = context.WithValue(ctx, paramName, intVal)
r = r.WithContext(ctx)
}
next.ServeHTTP(w, r)
})
}
}
func main() {
router := mux.NewRouter()
// Apply validation middleware to specific routes
validatedRouter := router.PathPrefix("/users").Subrouter()
validatedRouter.Use(validateIntParam("id", 1, 1000000)) // 1 to 1M user IDs
validatedRouter.HandleFunc("/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value("id").(int)
user := getUserByID(id) // Safe: id is validated
json.NewEncoder(w).Encode(user)
})
http.ListenAndServe(":8080", router)
}
Alternative approach using route-level validation:
router.HandleFunc("/items/{page:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
page, err := strconv.Atoi(vars["page"])
if err != nil || page < 1 || page > 10000 {
http.Error(w, "Invalid page number", http.StatusBadRequest)
return
}
// Safe pagination logic
items := getItemsWithPagination(page, 50)
json.NewEncoder(w).Encode(items)
}).Methods("GET")
For critical applications, consider using uint types for IDs that should never be negative, and always validate before any arithmetic operations:
id, err := strconv.ParseUint(vars["id"], 10, 64)
if err != nil || id == 0 {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Safe arithmetic with uint64
offset := (page - 1) * itemsPerPage
if offset > math.MaxUint64-itemsPerPage {
http.Error(w, "Page too large", http.StatusBadRequest)
return
}