HIGH mass assignmentfiber

Mass Assignment in Fiber

How Mass Assignment Manifests in Fiber

Mass assignment vulnerabilities in Fiber applications occur when user-supplied data is automatically bound to struct fields without proper authorization checks. In Go's Fiber framework, this typically happens when using the Context.Bind or Context.BindJSON methods to unmarshal request bodies directly into model structs.

Consider this common Fiber pattern:

type User struct {
    ID       string `json:"id"`
    Email    string `json:"email"`
    Password string `json:"password"`
    Role     string `json:"role"`
    IsActive bool   `json:"is_active"`
}

func UpdateUser(c *fiber.Ctx) error {
    var user User
    if err := c.BindJSON(&user); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
    }
    
    // Update database with all fields from user struct
    if err := db.UpdateUser(user.ID, user); err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    
    return c.JSON(fiber.Map{"message": "User updated"})
}

The vulnerability here is that an attacker can craft a JSON payload like:

{
    "id": "admin123",
    "email": "hacker@example.com",
    "password": "newpassword",
    "role": "admin",
    "is_active": true
}

This payload attempts to modify the user's role to admin, potentially escalating privileges. The BindJSON method indiscriminately maps all JSON fields to struct fields, including those the user shouldn't control.

Another Fiber-specific manifestation occurs with query parameters and form data:

func CreateProduct(c *fiber.Ctx) error {
    var product Product
    if err := c.Bind(&product); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
    }
    
    // Directly save all fields from request
    result, err := db.CreateProduct(product)
    if err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    
    return c.JSON(result)
}

Here, an attacker could manipulate fields like is_published, price, or category_id that should be controlled by the system, not the user.

Fiber-Specific Detection

Detecting mass assignment vulnerabilities in Fiber applications requires examining both code patterns and runtime behavior. Here's how to identify these issues:

Code Review Patterns:

Look for these red flags in your Fiber codebase:

// Dangerous: direct binding without field filtering
func DangerousHandler(c *fiber.Ctx) error {
    var model MyModel
    c.BindJSON(&model) // <-- Vulnerability here
    // ... uses model directly
}

// Safer: explicit field selection
func SafeHandler(c *fiber.Ctx) error {
    var input struct {
        Name  string `json:"name"`
        Email string `json:"email"`
    }
    if err := c.BindJSON(&input); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
    }
    
    // Only use the fields you explicitly expect
    user := User{
        Name:  input.Name,
        Email: input.Email,
    }
    // ... continue processing
}

Using middleBrick for Automated Detection:

middleBrick's black-box scanning approach can detect mass assignment vulnerabilities without requiring source code access. The scanner tests for:

  • Property Authorization: Attempts to modify fields that should be immutable or system-controlled
  • Input Validation: Tests for unexpected field injection
  • BOLA (Broken Object Level Authorization): Checks if users can modify objects they shouldn't access

To scan a Fiber API with middleBrick:

npm install -g middlebrick
middlebrick scan https://api.yourapp.com/user/update

The scanner will attempt to modify sensitive fields like role, admin, permissions, and system-controlled properties, reporting any successful modifications as mass assignment vulnerabilities.

Runtime Testing:

You can also test your Fiber endpoints manually:

# Test for mass assignment on user update endpoint
curl -X PUT https://api.yourapp.com/users/123 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test User",
    "email": "test@example.com",
    "role": "admin",
    "is_active": true,
    "created_at": "2000-01-01",
    "updated_at": "2000-01-01"
  }'

If the response shows that role, is_active, or timestamp fields were modified, you have a mass assignment vulnerability.

Fiber-Specific Remediation

Securing Fiber applications against mass assignment requires explicit field control and validation. Here are Fiber-specific remediation strategies:

1. Use Explicit Binding with Struct Filtering:

type UserUpdateInput struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func UpdateUser(c *fiber.Ctx) error {
    var input UserUpdateInput
    if err := c.BindJSON(&input); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
    }
    
    // Fetch existing user first
    userID := c.Params("id")
    user, err := db.GetUser(userID)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
    }
    
    // Only update allowed fields
    user.Name = input.Name
    user.Email = input.Email
    
    if err := db.UpdateUser(user); err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    
    return c.JSON(fiber.Map{"message": "User updated"})
}

2. Use Field-Level Authorization Tags:

type User struct {
    ID       string `json:"id" db:"id" auth:"read-only"`
    Email    string `json:"email" db:"email" auth:"user-can-update"`
    Password string `json:"password" db:"password" auth:"admin-only"`
    Role     string `json:"role" db:"role" auth:"admin-only"`
    IsActive bool   `json:"is_active" db:"is_active" auth:"admin-only"`
}

func UpdateUser(c *fiber.Ctx) error {
    var input map[string]interface{}
    if err := c.BindJSON(&input); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
    }
    
    userID := c.Params("id")
    user, err := db.GetUser(userID)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
    }
    
    // Check permissions for each field
    for field, value := range input {
        authLevel, exists := getAuthLevel(field)
        if !exists {
            continue // Ignore unknown fields
        }
        
        if !hasPermission(c, authLevel) {
            return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Permission denied for field: " + field})
        }
        
        // Update only authorized fields
        updateUserField(user, field, value)
    }
    
    if err := db.UpdateUser(user); err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    
    return c.JSON(fiber.Map{"message": "User updated"})
}

3. Use Middleware for Field Validation:

func FieldAuthorizationMiddleware(allowedFields []string) fiber.Handler {
    return func(c *fiber.Ctx) error {
        var input map[string]interface{}
        if err := c.BindJSON(&input); err != nil {
            return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
        }
        
        // Filter input to only allowed fields
        filtered := make(map[string]interface{})
        for _, field := range allowedFields {
            if value, exists := input[field]; exists {
                filtered[field] = value
            }
        }
        
        // Store filtered input for next handler
        c.Locals("filtered_input", filtered)
        return c.Next()
    }
}

// Usage
app.Put("/users/:id", FieldAuthorizationMiddleware([]string{"name", "email"}), UpdateUserHandler)

func UpdateUserHandler(c *fiber.Ctx) error {
    filteredInput := c.Locals("filtered_input").(map[string]interface{})
    
    // Rest of handler uses only filtered fields
    userID := c.Params("id")
    user, err := db.GetUser(userID)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
    }
    
    // Apply filtered updates
    if name, exists := filteredInput["name"]; exists {
        user.Name = name.(string)
    }
    if email, exists := filteredInput["email"]; exists {
        user.Email = email.(string)
    }
    
    if err := db.UpdateUser(user); err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    
    return c.JSON(fiber.Map{"message": "User updated"})
}

4. Integration with middleBrick for Continuous Security:

Integrate middleBrick into your Fiber development workflow to catch mass assignment vulnerabilities early:

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install middleBrick
        run: npm install -g middlebrick
      - name: Scan API endpoints
        run: |
          middlebrick scan https://staging.yourapp.com/api --fail-threshold C
        env:
          MIDDLEBRICK_API_KEY: ${{ secrets.MIDDLEBRICK_API_KEY }}

This GitHub Action configuration will scan your Fiber API endpoints on every pull request and fail the build if any endpoint receives a C grade or lower, ensuring mass assignment vulnerabilities are caught before production deployment.

Related CWEs: propertyAuthorization

CWE IDNameSeverity
CWE-915Mass Assignment HIGH

Frequently Asked Questions

How does middleBrick specifically detect mass assignment vulnerabilities in Fiber applications?
middleBrick uses black-box scanning to test for mass assignment by sending crafted payloads with unexpected fields to your Fiber endpoints. It attempts to modify sensitive fields like 'role', 'admin', 'permissions', and system-controlled properties that users shouldn't be able to change. The scanner analyzes responses to determine if these unauthorized modifications succeeded, mapping findings to OWASP API Top 10's 'Mass Assignment' category and providing specific remediation guidance for Go/Fiber applications.
Can middleBrick scan my Fiber API if it's behind authentication?
Yes, middleBrick can scan authenticated Fiber APIs. You can provide authentication credentials (API keys, JWT tokens, or basic auth) in the scan configuration. The scanner will use these credentials to access protected endpoints while still testing for mass assignment vulnerabilities in the authenticated context. This is particularly important since many mass assignment vulnerabilities only appear when users have certain permission levels.