Jomel.Tr
Web Vulnerabilities — Go
Прямая конкатенация пользовательского ввода в SQL-запрос.
vulnerable.go
func GetUser(db *sql.DB, id string) (*User, error) {
// id может быть: 1 OR 1=1 --
query := "SELECT * FROM users WHERE id = " + id
row := db.QueryRow(query)
var u User
err := row.Scan(&u.ID, &u.Name, &u.Email)
return &u, err
} secure.go
func GetUser(db *sql.DB, id string) (*User, error) {
// Параметризованный запрос — id всегда данные, не код
query := "SELECT * FROM users WHERE id = $1"
row := db.QueryRow(query, id)
var u User
err := row.Scan(&u.ID, &u.Name, &u.Email)
return &u, err
}Как исправить
Никогда не склеивайте SQL-строки с пользовательским вводом. Используйте только параметризованные запросы (placeholders $1, ?), при которых драйвер передаёт данные отдельно от тела запроса — ввод физически не может стать частью кода. Идентификаторы таблиц/колонок, которые нельзя параметризовать, проверяйте по allowlist. Права БД выдавайте по принципу наименьших привилегий.
Инструменты и практики
database/sql + placeholders— Стандартная библиотека: db.Query("... WHERE id = $1", id). Базовый и достаточный для большинства случаев способ.sqlc— Генерирует типобезопасный Go-код из обычного SQL на этапе сборки. Запросы проверяются компилятором, инъекции исключены by design.ent (entgo.io)— ORM от Meta с кодогенерацией и типобезопасным query-builder. Граф-ориентированная схема, никаких сырых строк.GORM— Популярный full-feature ORM. Параметризует автоматически; избегайте Raw/Exec с конкатенацией.sqlx / squirrel— sqlx — тонкая надстройка над database/sql; squirrel — безопасный query-builder, собирающий параметризованные запросы.pgx— Высокопроизводительный драйвер PostgreSQL с нативной поддержкой prepared statements и protocol-level биндингом.