В данной публикации разъясняется тестирование с внедрением time-based SQL-инъекций (на базе времени) в современных средах.
Больше о типах SQL-инъекций можно узнать здесь.
Важно: эта информация предоставляется исключительно в целях обучения специалистов по безопасности, чтобы быть осведомленными об угрозах и предотвращать такие атаки.
SQL-инъекция на основе времени – это тип атаки, когда злоумышленник проверяет наличие уязвимости на веб-сайте, измеряя время, необходимое для ответа базы данных. Он вводит SQL код в поле ввода данных, такое как для поиска или форму, чтобы база данных намеренно реагировала медленно.
Вместо того чтобы показывать ошибки или возвращать данные напрямую, как в случае с другими методами, SQL-инъекция на основе времени показывает злоумышленнику лишь произошедшую задержку. Например, злоумышленник может использовать SQL-запрос такого типа:
1' OR IF(1=1, SLEEP(5), 0) --
В этом примере, если база данных уязвима, она будет ждать 5 секунд, прежде чем ответить. Эта задержка сообщает злоумышленнику, что его код сработал, подтверждая, что база данных находится под угрозой.
Эффективность SQL-инъекции на основе времени сильно зависит от прямого и бесперебойного взаимодействия с базой данных, которую могут нарушить современные среды с обратными прокси-серверами, кэш-серверами и другими оптимизациями.
Современные веб-среды часто включают такие функции, как обратные прокси-серверы, кэширование и сети доставки контента (CDN), для улучшения производительности и обработки высокого трафика. Эти функции могут препятствовать проверкам безопасности, в частности, SQL-инъекциям на основе времени.
Как кэширование и прокси-серверы влияют на SQL-инъекции на основе времени
Распространенным примером является обратный прокси-сервер с кэшированием. Когда пентестер (или хакер) отправляет запрос с полезной нагрузкой SQL-инъекции на основе времени, например, 1′ OR IF(1=1, SLEEP(5), 0) —, первый запрос может достичь базы данных и вызвать 5-секундную задержку, что свидетельствует о возможной уязвимости. Если кэширование включено, прокси-сервер может сохранять этот ответ. Для повторяющихся идентичных запросов ответ может быть предоставлен из кэша без выполнения базы данных. Это может привести к тому, что пентестер ошибочно полагает, что уязвимость является ложноположительным результатом или не существует, поскольку ожидаемая задержка не наступает.

Сценарий тестирования для проверки SQL-инъекций на основе времени
Этот тест показывает, как обратный прокси-сервер кэширования, такой как Nginx, может влиять на тестирование уязвимостей SQL-инъекций на основе времени. Настроив Nginx в качестве обратного прокси-сервера с включенным кэшированием, можно увидеть, как повторяющиеся запросы обрабатываются по-разному.
Настройка Nginx для обратного прокси-сервера и кэширования
Nginx настроен для использования в качестве обратного прокси-сервера для бэкенд-программы PHP, подключенной к базе данных:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60s;
server {
listen 80;
# Configure the backend service
location / {
proxy_pass http://web:80;
proxy_cache my_cache; # Enable caching
proxy_cache_bypass $arg_cache_bypass; # Allows cache bypass if needed
proxy_cache_valid 200 10s; # Cache successful responses for 10 seconds
add_header X-Cache-Status $upstream_cache_status;
}
}
Настройка Docker Compose
Вот базовый пример файла docker-compose.yml, который настраивает среду с Nginx в качестве обратного прокси-сервера, PHP-приложения с уязвимой конечной точкой и базой данных MySQL.
Служба баз данных (база данных MySQL):
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: test
MYSQL_USER: tim
MYSQL_PASSWORD: test
ports:
- 3306:3306
volumes:
- ./dump:/docker-entrypoint-initdb.d
restart: always
container_name: mysql_database
Это инициализирует базу данных MySQL данными из dump.sql, обеспечивая тестовую базу данных для SQL-инъекции.
Веб-сервис (PHP-веб-приложение):
web:
build:
context: ./
container_name: php_web
depends_on:
- db
volumes:
- ./php/:/var/www/html/
ports:
- 8080:80
stdin_open: true
tty: true
restart: always
Этот сервис запускает уязвимое PHP-приложение, связывая его с базой данных и делая его доступным через порт 8080.
Сервис обратного прокси (обратный прокси-сервер Nginx):
rp:
image: nginx:latest
depends_on:
- web
ports:
- 80:85
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
restart: always
container_name: reverse_proxy
Это выполняет функцию обратного прокси-сервера. Также используется кастомная конфигурация из nginx.conf для включения кэширования.
Отправка полезных нагрузок

Как видно в правом нижнем углу, полезная нагрузка выполнена успешно, а ответ задержался на 5 секунд (X-Cache-Status: MISS).

Но второй ответ задержался всего на 13 мс из-за ответа сервера кэша.
Методы обхода кэша
Добавление уникальных параметров: добавляя случайный или уникальный параметр к каждому запросу, механизмы кэширования обрабатывают каждый запрос как новый. Например, можно добавить &cachebuster=12345 в конце URL-адреса, где 12345 – это случайное число, которое изменяется с каждым запросом.

Использование чисел с запятой: делая небольшие коррективы в значении задержки (например, не 5, а 5.0), механизмы кэширования обрабатывают каждый запрос как уникальный из-за разницы в структуре запроса. Например, использование SLEEP(5) в одном запросе и SLEEP(5.0) в следующем может помешать уровню кэширования распознать их как идентичные.

Использование арифметических операций: добавляя их в функцию задержки (например, SLEEP(3+2) или SLEEP(10/2) вместо SLEEP(5)), механизмы кэширования интерпретируют каждый запрос как уникальный из-за разницы в структуре запроса.

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

Использование лишних выражений в полезных нагрузках: добавление безвредных выражений, таких как 123=123 делает каждый запрос уникальным для механизмов кэширования, сохраняя при этом логику SQL неизменной. Вот как это работает для запроса 1′ OR IF(1=1, SLEEP(5), 0) AND 123=123 —:

Почему нужен этот подход
При тестировании на SQL-инъекции на основе времени возникла проблема после внедрения кэш-сервера. Когда тестирование было повторено с кэш-сервером, ответ предоставлялся непосредственно из кэша для идентичных запросов после первого, возвращаясь мгновенно без повторного выполнения SQL-запроса. В результате не была найдена SQL-инъекция, поскольку механизм кэширования маскировал задержку, которая обычно свидетельствует об успешной инъекции. Это показывает, как слои кэширования могут нарушать тестирование на основе времени, предоставляя немедленные, кэшированные ответы, полностью обходящие серверную часть, что приводит к пропущенным обнаружениям.
Результаты сканирования без кэш-сервера (уязвимость найдена):

Результаты сканирования при использовании кэш-сервера (уязвимость не найдена):

Выявление SQL-инъекций на основе времени
Для поиска таких уязвимостей можно использовать платформу Invicti (на основе Acunetix и Netsparker), которая находит большое количество сложных недостатков, подобных этому.
Чтобы бесплатно протестировать это решение, оставьте ваши контактные данные ниже, и мы с вами свяжемся:







