Using String Concatenation for Queries
Building SQL queries by concatenating strings with user input.
SQL injection vulnerabilities occur when user input is concatenated or formatted into SQL queries using fmt.Sprintf() or string concatenation instead of parameterized queries. This allows attackers to inject malicious SQL code that can read, modify, or delete data, potentially compromising the entire database.
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
func getUserByID(db *sql.DB, userID string) (*User, error) {
// VULNERABLE: String concatenation enables SQL injection
query := "SELECT id, username, email FROM users WHERE id = '" + userID + "'"
row := db.QueryRow(query)
var user User
err := row.Scan(&user.ID, &user.Username, &user.Email)
return &user, err
}
func searchUsers(db *sql.DB, search string) ([]User, error) {
// VULNERABLE: fmt.Sprintf allows injection
query := fmt.Sprintf("SELECT * FROM users WHERE username LIKE '%%%s%%'", search)
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
rows.Scan(&u.ID, &u.Username, &u.Email)
users = append(users, u)
}
return users, nil
}
// Attack: userID = "1' OR '1'='1"
// Attack: search = "'; DROP TABLE users; --"package main
import (
"database/sql"
_ "github.com/lib/pq"
)
func getUserByID(db *sql.DB, userID string) (*User, error) {
// SECURE: Parameterized query prevents SQL injection
query := "SELECT id, username, email FROM users WHERE id = $1"
row := db.QueryRow(query, userID)
var user User
err := row.Scan(&user.ID, &user.Username, &user.Email)
return &user, err
}
func searchUsers(db *sql.DB, search string) ([]User, error) {
// SECURE: Using parameterized query with placeholder
query := "SELECT * FROM users WHERE username LIKE $1"
searchPattern := "%" + search + "%"
rows, err := db.Query(query, searchPattern)
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
rows.Scan(&u.ID, &u.Username, &u.Email)
users = append(users, u)
}
return users, nil
}The vulnerable code uses string concatenation and fmt.Sprintf() to build SQL queries, allowing attackers to inject malicious SQL. The secure version uses parameterized queries with placeholders ($1, $2) that treat user input as data rather than executable SQL code.
Building SQL queries by concatenating strings with user input.
Sourcery automatically identifies sql injection via string formatting in go and many other security issues in your codebase.