Sql Injection in Fiber with Cockroachdb
Sql Injection in Fiber with Cockroachdb — how this specific combination creates or exposes the vulnerability
SQL injection in a Fiber application using CockroachDB arises when user-controlled input is concatenated into SQL strings rather than passed as parameterized values. CockroachDB, like other SQL databases, treats literal values and SQL syntax distinctly; failing to separate them allows an attacker to alter query structure. For example, an endpoint that builds a query by string interpolation can allow an attacker to append always-true conditions or additional statements, bypassing authentication or extracting data.
Consider a login handler that interpolates a username directly into a SQL string:
query := "SELECT id, password FROM users WHERE username = '" + username + "'"
If username is admin' --, the resulting query comments out the password check, potentially granting unauthorized access. CockroachDB’s SQL compatibility with PostgreSQL means common injection patterns such as UNION SELECT or nested subqueries work the same way. Because Fiber does not enforce any SQL safety layer, it is the developer’s responsibility to ensure queries are parameterized. The risk is not in CockroachDB itself but in how the driver is used: string concatenation or incorrect usage of the database/sql interface enables injection. In a black-box scan, middleBrick tests endpoints that accept input in URLs, headers, and JSON bodies, attempting to inject payloads such as ' OR 1=1 -- to see if authentication or data boundaries are bypassed.
Additional exposure occurs when dynamic database names or table names are constructed from user input, which cannot be parameterized with prepared statements. In such cases, strict allow-listing and schema validation are required. middleBrick’s checks for input validation and property authorization highlight these weaknesses by analyzing request surfaces and, where possible, inspecting OpenAPI specs to identify parameters that flow into query construction.
Cockroachdb-Specific Remediation in Fiber — concrete code fixes
Remediation centers on using parameterized queries and prepared statements so that user input is never interpreted as SQL. With CockroachDB and the pgx driver (or any database/sql-compatible driver), always use placeholders and pass arguments separately. Below are concrete, working examples for Fiber handlers.
Parameterized query with placeholders
Use $1, $2 style placeholders (PostgreSQL-compatible) and pass values as arguments. This ensures input is treated strictly as data.
package main
import (
"context"
"log"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer pool.Close()
app := fiber.New()
app.Get("/user/:id", func(c *fiber.Ctx) error {
var userID string = c.Params("id")
var name, email string
// Safe: parameterized query
row := pool.QueryRow(c.Context(), "SELECT name, email FROM users WHERE id = $1", userID)
if err := row.Scan(&name, &email); err != nil {
return c.Status(http.StatusNotFound).SendString("not found")
}
return c.JSON(fiber.Map{"name": name, "email": email})
})
log.Fatal(app.Listen(":3000"))
}
Prepared statement with db.Prepare
Prepare a statement once and reuse it; this is efficient and safe. Avoid preparing statements per request in high-load scenarios, but it remains correct.
package main
import (
"context"
"log"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer pool.Close()
// Prepare once, reuse
stmt, err := pool.Prepare(context.Background(), "get_user", "SELECT name, email FROM users WHERE id = $1")
if err != nil {
log.Fatalf("prepare failed: %v", err)
}
defer stmt.Close(context.Background())
app := fiber.New()
app.Get("/user/:id", func(c *fiber.Ctx) error {
var userID string = c.Params("id")
var name, email string
row := pool.QueryRow(c.Context(), stmt, userID)
if err := row.Scan(&name, &email); err != nil {
return c.Status(http.StatusNotFound).SendString("not found")
}
return c.JSON(fiber.Map{"name": name, "email": email})
})
log.Fatal(app.Listen(":3000"))
}
INSERT with multiple values
When inserting, use placeholders for each value and avoid building column lists dynamically from user input. If dynamic columns are unavoidable, use an allow-list and quote identifiers carefully (not via placeholders, which are for values only).
package main
import (
"context"
"log"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer pool.Close()
app := fiber.New()
app.Post("/user", func(c *fiber.Ctx) error {
var body struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := c.BodyParser(&body); err != nil {
return c.SendStatus(http.StatusBadRequest)
}
// Safe: placeholders for values
_, err = pool.Exec(c.Context(), "INSERT INTO users (name, email) VALUES ($1, $2)", body.Name, body.Email)
if err != nil {
return c.SendStatus(http.StatusInternalServerError)
}
return c.SendStatus(http.StatusCreated)
})
log.Fatal(app.Listen(":3000"))
}
Additional remediation steps include validating and allow-listing identifiers (table/column names) if dynamic SQL is required, and using the principle of least privilege for the database user used by Fiber. middleBrick’s checks for authentication, input validation, and property authorization can help surface remaining injection risks in unauthenticated and authenticated scans.
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 |