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

3. Подбор типов данных (NULL)

Подбор типов данных (NULL): Уточнение структуры

Знать количество колонок недостаточно — нужно, чтобы типы данных в UNION совпадали. В строгом мире SQL нельзя объединить числовой ID и текстовый пароль в одной колонке. Для решения этой задачи хакеры используют NULL — универсальное значение, которое совместимо с любым типом.

Посмотрим, как пошаговое замещение NULL реальными данными помогает найти «текстовые окна» для вывода секретной информации.


1. Механика: "Магия NULL"

Представьте запрос в Go-коде: SELECT id, name, price FROM products WHERE category = '%s' (через fmt.Sprintf).

Хакер уже узнал, что здесь 3 колонки. Но он не знает, где там строки, а где числа. Он начинает подставлять:

  1. category = 'Electronics' UNION SELECT 'a', NULL, NULL-- (Первая колонка — строка?) → Success (или Ошибка в Postgres)
  2. category = 'Electronics' UNION SELECT NULL, 'a', NULL-- (Вторая колонка — строка?) → Success (Появился текст на странице!)
  3. category = 'Electronics' UNION SELECT NULL, NULL, 'a'-- (Третья колонка — строка?) → Error (Там был численный прайс!)

2. Результат разведки: "Текст во второй колонке!"

Как только запрос с 'a' во второй позиции сработал, и на сайте вместо названия товара появилось слово 'a', хакер понимает: вторую колонку можно использовать для вывода паролей или секретных данных.


3. Таблица работы: Подбор типов

Попытка SQL-запрос (через Sprintf) Итог (Результат)
1 ... UNION SELECT 'a', NULL, NULL-- 🔴 Ошибка (Там был ID: INT)
2 ... UNION SELECT NULL, 'a', NULL-- 🟢 Успех (Там было Имя: TEXT)
3 ... UNION SELECT NULL, NULL, 'a'-- 🔴 Ошибка (Там был Прайс: NUM)

4. Как это выглядит в Go (database/sql)

Если ваш Go-код уязвим, хакерский запрос вернет ошибку в db.Query или rows.Scan. Но хакер видит 500 ошибку в браузере — и это для него тоже ответ. Если страница загрузилась со словом 'a' — значит он нашел "текстовую дыру".


5. Особенность Go: строгая типизация через Scan

В отличие от PHP/Python, где результаты SELECT часто читаются через mixed-тип, Go-драйвер database/sql строго типизирован: каждое значение колонки попадает в Go-переменную через rows.Scan(&p.ID, &p.Name, &p.Description, &p.Price, &p.Image). Если хоть один тип в UNION-части не совпадёт с типом исходной структуры — драйвер вернёт ошибку вида:

sql: Scan error on column index 0, name "id":
  converting driver.Value type string ("a") to a int: invalid syntax

Текст этой ошибки часто отображается прямо в HTML-ответе уязвимого приложения — и становится прямым подсказчиком структуры. Вместо подбора NULL-маски атакующий отправляет одинаковый строковый payload во все колонки и читает позиции, где драйвер ругается на несовместимость:

' UNION SELECT 'str','str','str','str','str' --

Каждое сообщение converting driver.Value type string to int указывает на колонку INT в исходной структуре. По итогам нескольких попыток собирается рабочий шаблон — например, INT, STRING, STRING, INT, STRING для каталога — и только потом подставляются реальные данные.

Вывод: для Go-приложений с Scan в типизированную структуру NULL-маска работает хуже, чем сравнение строкового payload с сообщениями об ошибках — это специфика Go, отсутствующая в динамически типизированных языках.


NULL — универсальная "затычка" в SQL. Она подходит к любому типу данных. Хакеру достаточно найти хотя бы одну текстовую колонку, чтобы вытащить данные всей вашей базы.

Теперь, когда структура полностью ясна, мы готовы перейти к самому интересному — извлечению реальной полезной нагрузки.

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

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

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

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