Integer Overflow in Echo Go
How Integer Overflow Manifests in Echo Go
Integer overflow in Echo Go typically occurs when handling numeric inputs that exceed the maximum value of the underlying integer type. In Go, integers have fixed sizes (int32, int64, etc.), and when arithmetic operations produce results larger than these limits, the value wraps around to negative numbers or zero.
A common Echo Go vulnerability appears in pagination logic. Consider this flawed implementation:
func getItems(c echo.Context) error {
limit := c.QueryParam("limit")
limitInt, _ := strconv.Atoi(limit)
// Vulnerable: no bounds checking
items := fetchItems(limitInt)
return c.JSON(http.StatusOK, items)
}If an attacker passes limit=9999999999, the value overflows a 32-bit integer, potentially causing unexpected database queries or memory allocation issues. In Echo Go's context binding, similar issues arise:
type Pagination struct {
Page int `query:"page"`
Limit int `query:"limit"`
}
func getItems(c echo.Context) error {
var p Pagination
if err := c.Bind(&p); err != nil { // Vulnerable if not properly validated
return err
}
// No validation of p.Limit bounds
return c.JSON(http.StatusOK, fetchItems(p.Page, p.Limit))
}Another Echo Go-specific scenario involves JWT claims processing. When decoding token claims that contain numeric values:
func verifyClaims(c echo.Context) error {
user := c.Get("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
roleID := int(claims["role_id"].(float64)) // Vulnerable cast
if roleID == 1 { // Admin check
return c.JSON(http.StatusOK, adminData)
}
return c.JSON(http.StatusOK, userData)
}The float64 to int conversion can overflow if the claim contains an unexpectedly large value, potentially bypassing authorization checks.
Echo Go-Specific Detection
Detecting integer overflow in Echo Go applications requires both static analysis and runtime testing. For static analysis, look for these patterns in your Echo Go codebase:
// Search for these vulnerable patterns:
strconv.Atoi() without bounds checking
c.Bind() on structs with int fields without validation
float64 to int conversions from external sources
Arithmetic operations on unvalidated inputs
// Use Go's vet tool with custom checks
go vet -vettool=$(which custom-vet) ./...
For runtime detection, middleBrick's API security scanner specifically tests for integer overflow vulnerabilities in Echo Go applications. The scanner sends boundary values to numeric parameters and analyzes responses for anomalies:
{ "integer_overflow": { "severity": "high", "category": "Input Validation", "finding": "Numeric parameter 'limit' accepts values that could overflow 32-bit integer", "remediation": "Implement bounds checking and use uint64 for large values", "evidence": "Response size increased by 10000% when sending limit=999999999" } }middleBrick tests Echo Go endpoints by sending values at the boundaries of common integer sizes (2^31-1, 2^63-1) and analyzing how the application handles them. The scanner also checks for error handling gaps where overflows might cause panics or unexpected behavior.
For comprehensive testing, combine middleBrick scans with unit tests that specifically target numeric boundaries:
func TestIntegerOverflow(t *testing.T) { e := echo.New() // Test boundary values testCases := []struct { name string input string expected int }{ {"normal", "100", 100}, {"max32", "2147483647", 2147483647}, {"overflow", "2147483648", 0}, // should fail safely } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/items?limit="+tc.input, nil) rec := httptest.NewRecorder() // Your handler logic here getItems(rec, req) // Verify safe handling if rec.Code == http.StatusOK { t.Errorf("Expected safe handling of overflow, got %d", rec.Code) } }) } }
Echo Go-Specific Remediation
Remediating integer overflow in Echo Go requires a defense-in-depth approach. Start with input validation using Echo's middleware system:
// Custom validation middleware
func validateIntBounds(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
limit := c.QueryParam("limit")
if limit == "" {
return next(c)
}
// Parse with error handling
limitInt, err := strconv.ParseInt(limit, 10, 64)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid limit parameter")
}
// Enforce safe bounds
const maxLimit = 1000
if limitInt < 1 || limitInt > maxLimit {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Limit must be between 1 and %d", maxLimit))
}
// Store validated value
c.Set("validatedLimit", int(limitInt))
return next(c)
}
}
// Apply middleware
ae := echo.New()
ae.Use(validateIntBounds)
ae.GET("/items", getItems)
For struct binding with bounds checking:
type Pagination struct {
Page int `query:"page" validate:"min=1"`
Limit int `query:"limit" validate:"min=1,max=1000"`
}
func getItems(c echo.Context) error {
var p Pagination
if err := c.Bind(&p); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
// Additional safe parsing
if p.Limit > 1000 {
p.Limit = 1000
}
return c.JSON(http.StatusOK, fetchItems(p.Page, p.Limit))
}For JWT claim processing, use safe type assertions:
func verifyClaims(c echo.Context) error {
user := c.Get("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
// Safe extraction with bounds
roleIDFloat, ok := claims["role_id"].(float64)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid role_id format")
}
roleID := int(roleIDFloat)
if roleID < 0 || roleID > 1000000 { // Reasonable bounds
return echo.NewHTTPError(http.StatusBadRequest, "Invalid role_id value")
}
if roleID == 1 {
return c.JSON(http.StatusOK, adminData)
}
return c.JSON(http.StatusOK, userData)
}For arithmetic operations, use Go's math/big package for arbitrary precision when needed:
import "math/big"
func safeAdd(a, b int64) (int64, error) {
bigA := big.NewInt(a)
bigB := big.NewInt(b)
result := big.NewInt(0).Add(bigA, bigB)
// Check if result fits in int64
if !result.IsInt64() {
return 0, errors.New("integer overflow")
}
return result.Int64(), nil
}
// Usage in Echo handler
func calculate(c echo.Context) error {
a := c.QueryParam("a")
b := c.QueryParam("b")
aInt, _ := strconv.ParseInt(a, 10, 64)
bInt, _ := strconv.ParseInt(b, 10, 64)
result, err := safeAdd(aInt, bInt)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Calculation overflow")
}
return c.JSON(http.StatusOK, map[string]int64{"result": result})
}