HIGH nosql injectionecho go

Nosql Injection in Echo Go

How Nosql Injection Manifests in Echo Go

Nosql Injection in Echo Go applications typically occurs when user input is directly incorporated into MongoDB queries without proper sanitization. Echo Go's minimalist design makes it easy to accidentally create vulnerable endpoints that accept JSON payloads and use them to construct database queries.

The most common pattern involves Echo handlers that accept request bodies and pass them directly to MongoDB methods. Consider this vulnerable Echo Go endpoint:

func getUser(c echo.Context) error {
    // Vulnerable: directly uses request body as query filter
    var filter bson.M
    if err := json.NewDecoder(c.Request().Body).Decode(&filter); err != nil {
        return err
    }
    
    collection := mongoClient.Database("test").Collection("users")
    var result User
    
    // Attacker controls the entire filter document
    err := collection.FindOne(context.Background(), filter).Decode(&result)
    if err != nil {
        return err
    }
    
    return c.JSON(http.StatusOK, result)
}

An attacker could send:

{
  "$where": "this.isAdmin === true",
  "username": { "$ne": null }
}

This bypasses authentication by injecting a JavaScript filter that returns all admin users. The vulnerability stems from Echo Go's flexible JSON binding—it accepts any structure and passes it directly to the database layer.

Another Echo Go-specific pattern involves using c.Bind() with struct tags that map directly to database fields:

type UserFilter struct {
    Username string `json:"username"`
    Role     string `json:"role"`
}

func searchUsers(c echo.Context) error {
    var filter UserFilter
    if err := c.Bind(&filter); err != nil {
        return err
    }
    
    // Even with struct binding, field values can contain injection
    collection := mongoClient.Database("test").Collection("users")
    query := bson.M{"role": filter.Role}
    
    // If filter.Role = "admin", {$ne: null}", this creates:
    // {"role": {"$ne": null, "$ne": "admin"}}
    cursor, err := collection.Find(context.Background(), query)
    if err != nil {
        return err
    }
    
    return c.JSON(http.StatusOK, cursor)
}

The issue becomes more severe when Echo Go handlers accept nested JSON objects that map to complex MongoDB queries, allowing attackers to construct arbitrary query operators like $or, $and, $expr, and $where clauses.

Echo Go-Specific Detection

Detecting Nosql Injection in Echo Go applications requires examining both the code structure and runtime behavior. middleBrick's scanner identifies Echo Go-specific patterns through several mechanisms:

Static Analysis: The scanner examines Echo Go route handlers for dangerous patterns like direct JSON decoding into BSON objects, unvalidated c.Bind() calls, and MongoDB operations that accept dynamic query parameters. It specifically looks for:

  • echo.Context.Bind() calls that populate structs used in database queries
  • json.Decoder usage that creates BSON documents from request bodies
  • MongoDB Find(), FindOne(), UpdateOne(), DeleteOne() calls with dynamic parameters
  • Echo Go's default JSON binding without validation middleware
  • Missing input sanitization before database operations

Dynamic Testing: middleBrick actively probes Echo Go endpoints with Nosql Injection payloads. For a typical Echo Go API at https://api.example.com/v1/users, it sends test requests containing:

POST /v1/users/search
Content-Type: application/json

{
  "$where": "sleep(1000) && this.username == 'test'",
  "username": {"$ne": null}
}

The scanner measures response timing to detect JavaScript execution and analyzes response structures for data leakage. It also tests for common MongoDB injection patterns like:

  • $ne with null to bypass filters
  • $or with always-true conditions
  • $where with JavaScript code execution
  • $regex with wildcard patterns
  • ObjectId injection in URL parameters

Echo Go-Specific Checks: middleBrick recognizes Echo Go's conventions and tests accordingly:

  • Endpoints using echo.Context.JSON() for responses
  • Handlers with echo.Context.Param() for URL parameter extraction
  • Echo Go middleware chains that might skip validation
  • Common Echo Go project structures and naming conventions

The scanner generates a security score with specific findings for each vulnerable endpoint, showing the exact injection payload that succeeded and the potential impact (data exposure, authentication bypass, denial of service).

Echo Go-Specific Remediation

Securing Echo Go applications against Nosql Injection requires both architectural changes and input validation. The most effective approach combines strict typing with parameterized queries.

1. Use Struct Binding with Validation:

type UserSearchParams struct {
    Username string `json:"username" validate:"omitempty,alphanum,max=50"`
    Role     string `json:"role" validate:"omitempty,oneof=admin user guest"`
    Active   *bool  `json:"active" validate:"omitempty"`
}

func searchUsers(c echo.Context) error {
    var params UserSearchParams
    if err := c.Bind(&params); err != nil {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid input"})
    }
    
    // Validate using go-playground/validator
    if err := c.Validate(&params); err != nil {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid parameters"})
    }
    
    // Build query safely with known fields
    query := bson.M{}
    if params.Username != "" {
        query["username"] = params.Username
    }
    if params.Role != "" {
        query["role"] = params.Role
    }
    if params.Active != nil {
        query["active"] = *params.Active
    }
    
    collection := mongoClient.Database("test").Collection("users")
    cursor, err := collection.Find(context.Background(), query)
    if err != nil {
        return err
    }
    
    return c.JSON(http.StatusOK, cursor)
}

2. Implement Echo Go Middleware for Input Sanitization:

func nosqlInjectionMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        // Sanitize query parameters
        for key, values := range c.QueryParams() {
            for i, val := range values {
                sanitized := sanitizeInput(val)
                c.QueryParams()[key][i] = sanitized
            }
        }
        
        // Sanitize JSON body for POST/PUT/PATCH
        if c.Request().Body != nil {
            body, err := io.ReadAll(c.Request().Body)
            if err != nil {
                return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid body"})
            }
            
            // Simple sanitization - remove suspicious operators
            sanitizedBody := removeMongoOperators(string(body))
            c.Request().Body = io.NopCloser(bytes.NewBufferString(sanitizedBody))
        }
        
        return next(c)
    }
}

// Register middleware globally
echo := echo.New()
echo.Use(nosqlInjectionMiddleware)

3. Use Echo Go's Built-in Validation with Custom Validators:

type SafeString struct {
    Value string `json:"value"`
}

func (s *SafeString) Sanitize() error {
    // Reject MongoDB operators
    if strings.Contains(s.Value, "$") {
        return errors.New("MongoDB operators not allowed")
    }
    // Reject JavaScript code
    if strings.Contains(s.Value, "function") || strings.Contains(s.Value, "return") {
        return errors.New("JavaScript code not allowed")
    }
    return nil
}

func getUser(c echo.Context) error {
    var params struct {
        Username SafeString `json:"username" validate:"required"`
    }
    
    if err := c.Bind(&params); err != nil {
        return err
    }
    
    if err := params.Username.Sanitize(); err != nil {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
    }
    
    collection := mongoClient.Database("test").Collection("users")
    query := bson.M{"username": params.Username.Value}
    
    var result User
    err := collection.FindOne(context.Background(), query).Decode(&result)
    if err != nil {
        return err
    }
    
    return c.JSON(http.StatusOK, result)
}

4. Use Echo Go's Error Handling for Security:

func secureHandler(c echo.Context) error {
    // Don't reveal database errors to clients
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Recovered in secureHandler: %v", r)
            c.JSON(http.StatusInternalServerError, map[string]string{"error": "Internal server error"})
        }
    }()
    
    // Validate all inputs before use
    username := c.QueryParam("username")
    if !isValidUsername(username) {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid username format"})
    }
    
    // Use context timeouts for database operations
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    collection := mongoClient.Database("test").Collection("users")
    query := bson.M{"username": username}
    
    var result User
    err := collection.FindOne(ctx, query).Decode(&result)
    if err != nil {
        if err == mongo.ErrNoDocuments {
            return c.JSON(http.StatusNotFound, map[string]string{"error": "User not found"})
        }
        return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Database error"})
    }
    
    return c.JSON(http.StatusOK, result)
}

These remediation strategies leverage Echo Go's strengths—its middleware system, validation support, and clean handler patterns—while adding security layers that prevent Nosql Injection attacks.

Frequently Asked Questions

How does middleBrick specifically detect Nosql Injection in Echo Go applications?
middleBrick scans Echo Go endpoints by first identifying route handlers that accept JSON input and perform MongoDB operations. It tests for injection by sending payloads containing MongoDB operators like $where, $ne, and $or to see if they're executed. The scanner also analyzes code patterns specific to Echo Go, such as c.Bind() calls that populate structs used in database queries, and checks for missing input validation middleware in the Echo Go middleware chain.
Can Nosql Injection in Echo Go lead to data exfiltration?
Yes, Nosql Injection in Echo Go can lead to complete data exfiltration. An attacker can use $where clauses to execute arbitrary JavaScript that returns all documents matching certain criteria, bypass authentication by injecting conditions that always evaluate to true, or use $regex with wildcard patterns to dump entire collections. Since Echo Go often returns JSON responses directly from database queries, successful injection can expose all user data, admin credentials, or sensitive application data without authentication.