Перейти к содержимому
Назад к пути
Теория 2 мин чтения

6. Почему fmt.Sprintf убивает безопасность

Почему fmt.Sprintf убивает безопасность в Go

Введение

Что общего у новичка в Go и уязвимого приложения? Оба обожают fmt.Sprintf. Это мощный, красивый инструмент форматирования строк. Но когда речь заходит о базах данных, fmt.Sprintf — это билет в один конец до взлома.

В этом подмодуле мы изучим Го-специфику: почему пересылка строки query через db.Query — это не безопасность, а имитация.


1. fmt.Sprintf vs db.Query(query, args)

В Go есть два способа сформировать и отправить запрос в базу данных. Один смертелен, второй — безопасен.

Вариант ❌: Смертельная конкатенация

// Хакер "вклеивается" в вашу строку на этапе Sprintf
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", username)
db.Query(query) // База получает ГОТОВУЮ строку 'SELECT... vasya OR 1=1'

В этом варианте Go просто подставил одну строку в другую. База данных видит цельную команду и ПАРСИТ её (выполняет).

Вариант ✅: Параметризованный запрос (Prepared)

// Мы разделяем КОД и ДАННЫЕ
query := "SELECT * FROM users WHERE name = ?"
db.Query(query, username) // Go отправляет в базу КОД и ДАННЫЕ РАЗДЕЛЬНО

2. Секрет на уровне протокола БД

В чем магия второго варианта? Когда вы используете db.Query(query, username), Go под капотом говорит базе:

  1. Шаблон: "Вот мой шаблон запроса: SELECT * FROM users WHERE name = ?. Подготовься к нему!"
  2. Данные: "А вот данные для этого шаблона: имя vasya. Просто подставь его и не вздумай выполнять его как код!"

Даже если в имени vasya будет вредоносный код ' OR '1'='1, база данных будет искать пользователя с ТАКИМ длинным и странным именем. Она не будет выполнять OR '1'='1'!


Таблица работы: Код vs Данные

Тип запроса Передача в БД Результат атаки
Sprintf Одной строкой ВЗЛОМ (база выполнит пэйлоад хакера)
Prepared Код + Данные раздельно БЕЗОПАСНО (база ищет юзера по имени)

3. Особенности разных баз данных (Placeholder)

В Go плейсхолдеры (?) могут различаться в зависимости от драйвера:

  • MySQL/SQLite: SELECT ... WHERE id = ?
  • PostgreSQL: SELECT ... WHERE id = $1
  • Oracle: SELECT ... WHERE id = :name

Но суть остается прежней: данные никогда не должны попадать в строку SQL через форматирование текста в самом Go.


Вывод

fmt.Sprintf — прекрасный инструмент для логов, но худший для SQL-запросов. Если вы видите fmt.Sprintf в коде работы с БД — бейте тревогу. В следующем модуле мы закрепим основы в квизе по вводной части, перед тем как перейти к реальной практике.

Продолжить чтение

Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу

Когда закончишь — отметь раздел, чтобы продолжить.

🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru