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

5. Уязвимости ORDER BY / GROUP BY (без Prepared)

Уязвимости ORDER BY: Где Prepared Statements бессильны

Динамическая сортировка (ORDER BY) — одна из самых коварных ловушек для Go-разработчика. Мы усвоили, что Prepared Statements защищают нас везде, где передаются данные (например, WHERE id = ?). Однако в SQL есть структурные элементы, которые нельзя параметризовать стандартным способом — это имена таблиц, колонок и направления сортировки.

Разберем, как возникают уязвимые API-интерфейсы и как злоумышленники используют «сортировку» для кражи данных.


1. Механика: "Ловушка ORDER BY"

Представьте типичный код для получения списка товаров с сортировкой: sortBy := c.Query("sort") (пользователь передает name или price). query := fmt.Sprintf("SELECT id, name FROM products ORDER BY %s", sortBy)

Хакеру не интересна очередность товаров. Он внедряет логическое условие: ?sort=1 AND (SELECT ASCII(SUBSTRING(password, 1, 1)) FROM users LIMIT 1) = 65

Что происходит: Если условие истинно (первая буква пароля — 'A'), база отсортирует результат по первой колонке. Если ложно — сортировка будет иной. Анализируя порядок элементов на странице, хакер постепенно восстанавливает секретные данные.


2. Почему обычные плейсхолдеры здесь не работают

Если вы попытаетесь использовать защиту «в лоб»: db.Query("... ORDER BY ?", sortBy), драйвер Go подставит значение как строку в кавычках.

  • Вы ожидали: ORDER BY price
  • База получила: ORDER BY 'price'

Для SQL-сервера ORDER BY 'price' — это сортировка по константе, то есть отсутствие какой-либо осмысленной сортировки. Именно поэтому разработчики часто возвращаются к небезопасной конкатенации, совершая фатальную ошибку.


3. Безопасность vs Уязвимость

Подход Код (Пример) Оценка безопасности
Опасный ORDER BY %s (прямая вставка) 🔴 SQL Injection
Надежный Сверка со списком (Whitelist) 🟢 Полная защита

4. Единственное верное решение: White-listing

Если вам нужна динамическая сортировка в Go, никогда не передавайте ввод пользователя напрямую в SQL. Единственный безопасный путь — проверить, входит ли полученная строка в заранее определенный список разрешенных колонок:

// ✅ БЕЗОПАСНО: Проверка по белому списку
allowed := map[string]bool{"name": true, "price": true}
if !allowed[sortBy] {
    sortBy = "id" // Значение по умолчанию
}
query := fmt.Sprintf("... ORDER BY %s", sortBy) // Теперь это безопасно

5. Сравнение подходов защиты ORDER BY

Критерий Fix A: Whitelist + database/sql Fix B: squirrel / ORM
Метод map[string]bool + fmt.Sprintf (только проверенные значения) sq.OrderBy() / db.Order() с whitelist
Зависимости Нет — только stdlib squirrel или GORM
Преимущество Простота, нет внешних зависимостей Fluent API, сложные сортировки без конкатенации
Важно Whitelist обязателен в обоих подходах — ни один query builder не валидирует имена колонок автоматически

Динамический SQL — это всегда риск. Хакеру достаточно внедрить одно условное выражение в блок сортировки, чтобы превратить ваш интерфейс в инструмент для посимвольного перебора паролей.

Мы завершили изучение методов обхода фильтров. После квиза нас ждет финальный раздел — знакомство с инструментами автоматизации SQL-инъекций.

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

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

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

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