HIGH sql injectionfiber

Sql Injection in Fiber

How SQL Injection Manifests in Fiber

SQL Injection in Fiber applications typically occurs when user input is directly concatenated into SQL queries without proper sanitization. Fiber's minimalist design means developers have full control over database interactions, which is powerful but also places the responsibility for security directly on the developer.

The most common pattern in Fiber involves using raw SQL strings with interpolated variables. For example:

func getUser(c *fiber.Ctx) error {
    id := c.Query("id")
    db := database.GetDB()
    var user User
    
    // Vulnerable: direct string interpolation
    err := db.QueryRow("SELECT * FROM users WHERE id = " + id).Scan(&user.ID, &user.Name)
    if err != nil {
        return c.Status(500).SendString("Error")
    }
    return c.JSON(user)
}

This code is vulnerable because an attacker can pass id=1 OR 1=1 to return all users, or id=1; DROP TABLE users; to delete data.

Another common Fiber-specific pattern involves using db.Exec with string formatting:

func createUser(c *fiber.Ctx) error {
    user := new(User)
    if err := c.BodyParser(user); err != nil {
        return c.Status(400).SendString("Invalid input")
    }
    
    db := database.GetDB()
    
    // Vulnerable: fmt.Sprintf creates SQL injection point
    query := fmt.Sprintf("INSERT INTO users (name, email) VALUES ('%s', '%s')", 
        user.Name, user.Email)
    
    _, err := db.Exec(query)
    if err != nil {
        return c.Status(500).SendString("Error creating user")
    }
    return c.Status(201).SendString("User created")
}

Attackers can exploit this by sending names like '); DROP TABLE users; -- to execute arbitrary SQL.

Even when using query parameters, improper ordering can create vulnerabilities:

func searchProducts(c *fiber.Ctx) error {
    category := c.Query("category")
    sort := c.Query("sort") // User-controlled sort column
    
    db := database.GetDB()
    
    // Vulnerable: sort column not validated
    query := fmt.Sprintf("SELECT * FROM products WHERE category = '%s' ORDER BY %s", 
        category, sort)
    
    rows, err := db.Query(query)
    if err != nil {
        return c.Status(500).SendString("Error")
    }
    defer rows.Close()
    
    // Process results...
}

Here, an attacker can pass sort=id; DROP TABLE products; -- to execute destructive queries.

Fiber-Specific Detection

Detecting SQL Injection in Fiber applications requires both static code analysis and dynamic 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 static detection, look for these Fiber-specific patterns:

Raw SQL concatenation:

// Dangerous pattern - look for these in your Fiber handlers
query := "SELECT * FROM users WHERE id = " + userInput
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)
query := fmt.Sprintf("UPDATE users SET email = '%s' WHERE id = %d", email, id)

Unsanitized query parameters in ORDER BY or LIMIT:

sort := c.Query("sort")
limit := c.Query("limit")
query := fmt.Sprintf("SELECT * FROM table ORDER BY %s LIMIT %s", sort, limit)

Dynamic table or column names:

table := c.Query("table")
query := fmt.Sprintf("SELECT * FROM %s WHERE id = %d", table, id)

middleBrick scans Fiber applications by sending specially crafted payloads to test for SQL injection vulnerabilities. The scanner tests:

  • Boolean-based injection: id=1 OR 1=1 to test if conditions are evaluated
  • Union-based injection: id=1 UNION SELECT 1,2,3 to test data extraction
  • Error-based injection: id=1 AND 1=2 to look for database error responses
  • Time-based injection: id=1 AND SLEEP(5) to test for delayed responses

The scanner also checks for HTTP response differences that indicate successful injection, such as different content lengths, response times, or error messages.

For Fiber applications using ORMs like GORM, middleBrick specifically tests for ORM injection patterns:

// GORM injection - look for dynamic query building
db.Where("name = ?", name).Or(fmt.Sprintf("id = %d", id)).Find(&results)

middleBrick's continuous monitoring feature (Pro plan) can be configured to regularly scan your Fiber API endpoints, alerting you if new vulnerabilities are introduced during development.

Fiber-Specific Remediation

Remediating SQL Injection in Fiber applications requires using parameterized queries and input validation. Here are Fiber-specific solutions:

1. Use Prepared Statements with Parameter Binding

The most effective defense is using prepared statements with parameter binding:

func getUser(c *fiber.Ctx) error {
    id := c.Query("id")
    db := database.GetDB()
    var user User
    
    // Safe: parameterized query
    err := db.QueryRow("SELECT * FROM users WHERE id = ?", id).Scan(&user.ID, &user.Name)
    if err != nil {
        return c.Status(404).SendString("User not found")
    }
    return c.JSON(user)
}

func createUser(c *fiber.Ctx) error {
    user := new(User)
    if err := c.BodyParser(user); err != nil {
        return c.Status(400).SendString("Invalid input")
    }
    
    db := database.GetDB()
    
    // Safe: parameterized INSERT
    result, err := db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", 
        user.Name, user.Email)
    if err != nil {
        return c.Status(500).SendString("Error creating user")
    }
    
    id, _ := result.LastInsertId()
    return c.Status(201).JSON(fiber.Map{"id": id})
}

2. Input Validation and Whitelisting

For dynamic values like sort columns or table names, use strict whitelisting:

var allowedSortColumns = map[string]bool{
    "id": true,
    "name": true,
    "created_at": true,
    "updated_at": true,
}

func searchProducts(c *fiber.Ctx) error {
    category := c.Query("category")
    sort := c.Query("sort")
    
    // Validate sort column against whitelist
    if !allowedSortColumns[sort] {
        sort = "id" // default to safe value
    }
    
    db := database.GetDB()
    
    // Safe: sort column is validated, parameters are bound
    query := fmt.Sprintf("SELECT * FROM products WHERE category = ? ORDER BY %s", sort)
    rows, err := db.Query(query, category)
    if err != nil {
        return c.Status(500).SendString("Error")
    }
    defer rows.Close()
    
    // Process results...
}

3. Using Fiber's Middleware for Input Sanitization

Create reusable middleware for input validation:

func sqlInjectionProtection(next fiber.Handler) fiber.Handler {
    return func(c *fiber.Ctx) error {
        // Check for suspicious patterns in query parameters
        for key, value := range c.Query() {
            if strings.Contains(value, "' OR ") || 
               strings.Contains(value, "' UNION ") ||
               strings.Contains(value, "; DROP ") {
                return c.Status(400).SendString("Invalid input detected")
            }
        }
        
        // Check JSON body for dangerous patterns
        if c.Context().IsJSON() {
            var body map[string]interface{}
            if err := json.Unmarshal(c.Body(), &body); err == nil {
                for _, value := range body {
                    if str, ok := value.(string); ok {
                        if strings.Contains(str, "' OR ") || 
                           strings.Contains(str, "' UNION ") {
                            return c.Status(400).SendString("Invalid input detected")
                        }
                    }
                }
            }
        }
        
        return next(c)
    }
}

// Use in your Fiber app
app.Use(sqlInjectionProtection)

4. ORM Best Practices with GORM

When using GORM with Fiber, avoid dynamic query building:

// Safe: parameterized queries
func getUsers(c *fiber.Ctx) error {
    name := c.Query("name")
    
    db := database.GetDB()
    var users []User
    
    // Safe: GORM handles parameterization
    result := db.Where("name = ?", name).Find(&users)
    
    if result.Error != nil {
        return c.Status(500).SendString("Error")
    }
    
    return c.JSON(users)
}

// Avoid this dangerous pattern:
// db.Where(fmt.Sprintf("name = '%s'", name)).Find(&users)

5. Using Database-Specific Features

Leverage database features for additional protection:

func getUserWithLimit(c *fiber.Ctx) error {
    id := c.Query("id")
    limit := c.Query("limit")
    
    // Validate limit as integer
    limitVal, err := strconv.Atoi(limit)
    if err != nil || limitVal > 100 {
        limitVal = 10 // enforce maximum limit
    }
    
    db := database.GetDB()
    var user User
    
    // Safe: parameterized query with validated limit
    err = db.QueryRow("SELECT * FROM users WHERE id = ? LIMIT ?", id, limitVal).Scan(&user.ID, &user.Name)
    if err != nil {
        return c.Status(404).SendString("User not found")
    }
    return c.JSON(user)
}

middleBrick's remediation guidance includes specific code examples for your detected vulnerabilities, showing exactly how to fix the issues found in your Fiber application.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

How can I test my Fiber API for SQL Injection vulnerabilities?
You can test your Fiber API using middleBrick's black-box scanning. Simply submit your API endpoint URL to middleBrick, which will automatically test for SQL injection using various payloads including boolean-based, union-based, and time-based injection techniques. The scan takes 5-15 seconds and provides a security score with detailed findings. For continuous testing, the Pro plan includes scheduled scans that alert you to new vulnerabilities as they're introduced.
Does middleBrick work with Fiber applications using ORMs like GORM?
Yes, middleBrick detects SQL injection vulnerabilities in Fiber applications regardless of whether you're using raw SQL, GORM, or other database libraries. The scanner tests the actual API endpoints and identifies injection points in query parameters, request bodies, and headers. For GORM specifically, middleBrick checks for dangerous patterns like dynamic query building with fmt.Sprintf and ensures parameterized queries are used correctly.