HIGH insecure direct object referencefiber

Insecure Direct Object Reference in Fiber

How Insecure Direct Object Reference Manifests in Fiber

Insecure Direct Object Reference (IDOR) in Fiber applications typically occurs when user input is directly used to access resources without proper authorization checks. This vulnerability is particularly common in Fiber's handler functions where developers assume that if a user can see an ID, they should have access to the resource.

A classic Fiber IDOR pattern looks like this:

app.Get("/api/users/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    user, err := getUserByID(id)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
    }
    return c.JSON(user)
})

The critical flaw here is that the handler retrieves any user by ID without verifying whether the requesting user has permission to view that specific user's data. An authenticated attacker can simply increment the ID parameter to access other users' information.

Another Fiber-specific manifestation occurs with path traversal combined with IDOR:

app.Get("/api/files/:filename", func(c *fiber.Ctx) error {
    filename := c.Params("filename")
    content, err := os.ReadFile("/var/files/" + filename)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "File not found"})
    }
    return c.JSON(fiber.Map{"content": content})
})

This pattern is dangerous because it allows direct file access without validating the user's permissions. An attacker could request ../../../etc/passwd or access files belonging to other users.

Database IDOR in Fiber often appears with ORM operations:

app.Get("/api/orders/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    order := models.Order{}
    db.First(&order, id)
    return c.JSON(order)
})

Even though the database query works correctly, there's no check to ensure the authenticated user owns this order. Any authenticated user can view any order by changing the ID parameter.

Fiber's middleware-based architecture can exacerbate IDOR if authentication middleware doesn't properly set user context. A common anti-pattern:

app.Use(authMiddleware)

app.Get("/api/profile/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    // Missing: userID := c.Locals("userID")
    // Missing: if id != userID { return c.Status(fiber.StatusForbidden) }
    
    profile, err := getProfileByID(id)
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Profile not found"})
    }
    return c.JSON(profile)
})

The authentication middleware sets user context in c.Locals, but the handler fails to compare the requested resource ID with the authenticated user's ID, creating an IDOR vulnerability.

Fiber-Specific Detection

Detecting IDOR vulnerabilities in Fiber applications requires both manual code review and automated scanning. middleBrick's black-box scanning approach is particularly effective for Fiber APIs because it tests the actual runtime behavior without needing source code access.

For manual detection in Fiber applications, look for these patterns:

Direct parameter usage without authorization:

app.Get("/api/resources/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    resource := getResourceByID(id) // No permission check!
    return c.JSON(resource)
})

Missing ownership verification:

app.Get("/api/users/:id/profile", func(c *fiber.Ctx) error {
    id := c.Params("id")
    // Should verify: if id != c.Locals("userID") { return forbidden }
    profile := getUserProfile(id)
    return c.JSON(profile)
})

Database operations without user scoping:

app.Get("/api/posts/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    post := models.Post{}
    db.First(&post, id) // No WHERE user_id = ? clause
    return c.JSON(post)
})

middleBrick scans Fiber APIs by automatically testing these patterns. It attempts authenticated requests with manipulated IDs to detect whether resources can be accessed across user boundaries. The scanner tests both numeric ID sequences (incrementing IDs to find adjacent records) and parameterized endpoints that might expose other users' data.

For Fiber applications, middleBrick specifically checks:

  • Parameter tampering on all authenticated endpoints
  • Cross-user data access attempts
  • Path traversal vulnerabilities in file-serving endpoints
  • Database query patterns that might expose unauthorized records
  • Missing authorization checks in middleware chains
  • API endpoints that accept user IDs without validation

The scanner's 12 parallel security checks include BOLA (Broken Object Level Authorization) testing, which is the formal category for IDOR vulnerabilities. middleBrick attempts to access resources belonging to other users by systematically varying input parameters and analyzing the responses for data leakage.

For Fiber developers using OpenAPI specifications, middleBrick can analyze your .yaml or .json spec files to identify endpoints that might be vulnerable to IDOR based on their parameter patterns and authentication requirements.

Fiber-Specific Remediation

Remediating IDOR vulnerabilities in Fiber applications requires implementing proper authorization checks and resource scoping. Here are Fiber-specific remediation patterns:

1. User Context Middleware:

func setUserContext(next fiber.Handler) fiber.Handler {
    return func(c *fiber.Ctx) error {
        userID := c.Locals("userID")
        if userID == nil {
            return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Authentication required"})
        }
        
        // Store user object for downstream handlers
        user := getUserByID(userID.(string))
        c.Locals("user", user)
        
        return next(c)
    }
}

app.Use(setUserContext)

// Now all handlers can access c.Locals("user")
app.Get("/api/profile", func(c *fiber.Ctx) error {
    user := c.Locals("user").(*User)
    return c.JSON(user)
})

2. Resource Ownership Validation:

func checkResourceOwnership(next fiber.Handler) fiber.Handler {
    return func(c *fiber.Ctx) error {
        resourceID := c.Params("id")
        userID := c.Locals("userID").(string)
        
        owns, err := userOwnsResource(userID, resourceID)
        if err != nil || !owns {
            return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
        }
        
        return next(c)
    }
}

// Apply to specific routes
app.Get("/api/orders/:id", checkResourceOwnership, func(c *fiber.Ctx) error {
    id := c.Params("id")
    order := getOrderByID(id)
    return c.JSON(order)
})

3. Database Query Scoping:

app.Get("/api/orders", func(c *fiber.Ctx) error {
    userID := c.Locals("userID").(string)
    
    var orders []models.Order
    db.Where("user_id = ?", userID).Find(&orders)
    return c.JSON(orders)
})

app.Get("/api/orders/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    userID := c.Locals("userID").(string)
    
    var order models.Order
    result := db.Where("id = ? AND user_id = ?", id, userID).First(&order)
    if result.RowsAffected == 0 {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Order not found or access denied"})
    }
    return c.JSON(order)
})

4. IDOR Prevention Middleware:

func idorPrevention(next fiber.Handler) fiber.Handler {
    return func(c *fiber.Ctx) error {
        // Check if route has :id parameter
        route := c.Route()
        for _, param := range route.Params {
            if param == "id" {
                // Get the ID from params
                id := c.Params("id")
                
                // Get current user ID from context
                userID := c.Locals("userID")
                
                // Check if user owns this resource
                if !userHasAccessToResource(userID, id) {
                    return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
                }
                break
            }
        }
        
        return next(c)
    }
}

app.Use(idorPrevention)

5. File Access Authorization:

app.Get("/api/files/:filename", func(c *fiber.Ctx) error {
    filename := c.Params("filename")
    userID := c.Locals("userID").(string)
    
    // Validate filename to prevent path traversal
    if strings.Contains(filename, "..") || filepath.IsDir(filename) {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid filename"})
    }
    
    // Check if user owns this file
    if !userOwnsFile(userID, filename) {
        return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
    }
    
    content, err := os.ReadFile(filepath.Join("/var/files", filename))
    if err != nil {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "File not found"})
    }
    
    return c.JSON(fiber.Map{"content": content})
})

6. Using Fiber's Context Features:

app.Get("/api/users/:userId/posts", func(c *fiber.Ctx) error {
    requestedUserID := c.Params("userId")
    currentUserID := c.Locals("userID").(string)
    
    // Only allow viewing own posts or admin access
    if requestedUserID != currentUserID && !c.Locals("isAdmin").(bool) {
        return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "You can only view your own posts"})
    }
    
    var posts []models.Post
    db.Where("user_id = ?", requestedUserID).Find(&posts)
    return c.JSON(posts)
})

The key remediation principle is always validating that the authenticated user has permission to access the specific resource they're requesting, never assuming that possession of an ID implies authorization.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

How does middleBrick detect IDOR vulnerabilities in Fiber applications?
middleBrick performs black-box scanning by sending authenticated requests with manipulated parameters to test for unauthorized data access. It systematically varies ID parameters, tests path traversal patterns, and analyzes responses to detect when resources belonging to other users can be accessed. The scanner runs 12 parallel security checks including BOLA testing specifically designed to identify IDOR vulnerabilities without requiring source code access.
Can I integrate middleBrick IDOR scanning into my Fiber CI/CD pipeline?
Yes, with middleBrick's Pro plan you can add the GitHub Action to your repository. The action scans your Fiber APIs during the build process and can fail the build if security scores drop below your configured threshold. This ensures IDOR vulnerabilities are caught before deployment. The CLI tool also allows you to script scans as part of your testing workflow, with JSON output that can be integrated into your existing CI/CD tooling.