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=1to test if conditions are evaluated - Union-based injection:
id=1 UNION SELECT 1,2,3to test data extraction - Error-based injection:
id=1 AND 1=2to 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 ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |