Что такое SQL-инъекции и как с ними бороться в Go?

Ответ

SQL-инъекция — это атака, при которой злоумышленник внедряет вредоносный SQL-код в запрос к базе данных. Это происходит, когда приложение конструирует SQL-запросы путем простой конкатенации строк с пользовательским вводом.

Основной и самый надежный способ борьбы с SQL-инъекциями в Go — параметризация запросов.

Вместо того чтобы вставлять данные напрямую в строку запроса, вы используете специальные маркеры (плейсхолдеры), а сами данные передаете как отдельные аргументы. Драйвер базы данных сам позаботится о безопасном экранировании.

Способы реализации:

  1. Позиционные плейсхолдеры (стандартный database/sql) Плейсхолдеры зависят от драйвера БД (? для MySQL, $1, $2... для PostgreSQL).

    // Для PostgreSQL
    rows, err := db.Query("SELECT name FROM users WHERE id = $1", userID)
    
    // Для MySQL
    rows, err := db.Query("SELECT name FROM users WHERE id = ?", userID)
  2. Именованные параметры (библиотека sqlx) Улучшает читаемость кода, особенно при большом количестве параметров.

    user := User{ID: 1, Name: "Alice"}
    _, err := db.NamedExec(`INSERT INTO users (id, name) VALUES (:id, :name)`, user)

Что нельзя делать: Никогда не конструируйте запросы вот так:

// УЯЗВИМЫЙ КОД!
query := fmt.Sprintf("SELECT name FROM users WHERE id = %s", userID)
rows, err := db.Query(query)

Важно: Параметризация работает только для значенийWHERE, VALUES, SET). Она не работает для динамических имен таблиц или столбцов. В таких редких случаях необходимо формировать "белый список" разрешенных имен или использовать функцию QuoteIdentifier из драйвера, если она доступна.