> Может ли в SQL-запросе быть инъекция и как ее предотвратить (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Т-Банк

Стек: Go

> Пример ответа

Короткий ответ

Да, SQL-инъекция возможна в любом языке, включая Go, если запрос строится конкатенацией строк или через fmt.Sprintf с пользовательским вводом. Предотвращается использованием параметризованных запросов (database/sql с плейсхолдерами ? или $1), валидацией и экранированием входных данных, а также принципом наименьших привилегий для БД-пользователя. В Go нет магической защиты - ответственность на разработчике.

Подробное объяснение

SQL-инъекция возникает, когда непроверенные пользовательские данные попадают в текст SQL-запроса. Атакующий может изменить структуру запроса, добавив OR 1=1, UNION SELECT, комментарии -- или вложенные подзапросы. В Go типичный вектор - использование fmt.Sprintf("SELECT * FROM users WHERE id = %s", userInput) или конкатенация строк.

Параметризованные запросы (PreparedStatement) решают проблему на уровне драйвера: значения передаются отдельно от SQL-кода, и драйвер экранирует их как литералы. В database/sql это выглядит как db.Query("SELECT * FROM users WHERE id = ?", id) для MySQL или $1 для PostgreSQL. Важно: параметризация работает только для значений, не для идентификаторов (имён таблиц, колонок) - их нужно валидировать отдельно через whitelist.

Дополнительные меры: валидация типов и форматов на уровне приложения (например, strconv.Atoi для чисел), использование ORM с параметризацией по умолчанию (GORM, sqlx), ограничение прав БД-пользователя (только SELECT для чтения, отдельный пользователь для записи), логирование и мониторинг подозрительных запросов.

На практике

В Go с database/sql всегда используйте плейсхолдеры. Для динамических частей SQL (ORDER BY, LIMIT) применяйте whitelist-маппинг: map[string]string{"name": "name", "id": "id"} и проверяйте ввод по ключу. Для LIKE-запросов экранируйте % и _ в пользовательском вводе перед подстановкой как параметр. Для массовых вставок используйте Batch из pgx или цикл с prepared statements.

Не полагайтесь на экранирование через strings.Replace - это ненадёжно. Используйте sql.Named для именованных параметров, если нужно больше читаемости. Для сложных фильтров - стройте WHERE-условия динамически, но значения всегда через параметры.

Пример кода

GO
// Плохо: инъекция
id := r.URL.Query().Get("id")
rows, err := db.Query(fmt.Sprintf("SELECT * FROM users WHERE id = %s", id))
// Хорошо: параметризованный запрос
id := r.URL.Query().Get("id")
rows, err := db.Query("SELECT * FROM users WHERE id = ?", id)
// Динамический ORDER BY через whitelist
allowedOrder := map[string]string{
"name": "name",
"id": "id",
}
orderBy, ok := allowedOrder[r.URL.Query().Get("sort")]
if !ok {
orderBy = "id"
}
rows, err := db.Query("SELECT * FROM users ORDER BY "+orderBy, limit)

Как отвечать на собеседовании

Начните с прямого ответа "да, возможна", затем кратко объясните механизм. Покажите понимание различий между параметризацией и экранированием. Упомяните, что в Go нет встроенной защиты, но database/sql предоставляет безопасный API. Приведите пример плохого и хорошего кода. Если спросят про динамические части запроса - расскажите про whitelist. Завершите упоминанием дополнительных мер: валидация, права БД, мониторинг.

Что проверяет интервьюер

  • Понимание сути инъекции, а не заученных ответов
  • Умение применять параметризацию в Go на практике
  • Знание ограничений параметризации (идентификаторы, LIKE)
  • Осознание ответственности разработчика за безопасность
  • Способность рассуждать о trade-off между удобством и безопасностью

Типичные ошибки

  • Утверждение, что Go защищает от инъекций "из коробки"
  • Предложение экранировать строки через strings.Replace как основную защиту
  • Использование параметризации для имён таблиц/колонок без whitelist
  • Игнорирование LIKE-запросов с % и _
  • Ответ без примера кода - интервьюер ждёт конкретики
  • Смешивание понятий "валидация" и "параметризация" - это разные уровни защиты

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью