Техніки обходу кешу для SQL-ін’єкції на основі часу

У цій публікації пояснюється тестування з використанням 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-секундну затримку, що свідчить про можливу вразливість. Але коли кешування ввімкнено, проксі-сервер може зберігати цю відповідь. Для повторюваних ідентичних запитів відповідь може бути надана з кешу без виконання базою даних. Це може призвести до того, що пентестер помилково вважатиме, що вразливість є хибнопозитивним результатом або не існує, оскільки очікувана затримка не настає.

caching and proxies affect time-based SQLi (1)

Сценарій тестування для перевірки 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 для ввімкнення кешування.

Надсилання корисних навантажень

Running payloads sqli (1)

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

Running payloads sqli 2

Але друга відповідь затрималася лише на 13 мс через відповідь сервера кешу.

Методи обходу кешу

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

Delayed 5 s (X-Cache-Status MISS)
Затримка 5 с. (X-Cache-Status: MISS)

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

Delayed 5 s (X-Cache-Status MISS) 2
Затримка 5 с. (X-Cache-Status: MISS)

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

Delayed 5 s. (X-Cache-Status: MISS)
Затримка 5 с. (X-Cache-Status: MISS)

Додавання коментарів до корисних навантажень: вставляючи випадкові коментарі, можна зробити кожен запит унікальним для механізмів кешування, навіть якщо логіка запиту залишається незмінною. Ось приклад використання:

Delayed 5 s (X-Cache-Status MISS) 4
Затримка 5 с. (X-Cache-Status: MISS)

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

Delayed 5 s (X-Cache-Status MISS) 5
Затримка 5 с. (X-Cache-Status: MISS)

Чому потрібен цей підхід

Під час тестування на SQL-ін’єкції на основі часу виникла проблема після впровадження кеш-сервера. Коли тестування було повторено з кеш-сервером, відповідь надавалася безпосередньо з кешу для ідентичних запитів після першого, повертаючись миттєво без повторного виконання SQL-запиту. В результаті не було знайдено SQL-ін’єкцію, оскільки механізм кешування маскував затримку, яка зазвичай свідчить про успішну ін’єкцію. Це показує, як шари кешування можуть порушувати тестування на основі часу, надаючи негайні, кешовані відповіді, які повністю обходять серверну частину, що призводить до пропущених виявлень.

Результати сканування без кеш-сервера (вразливість знайдено):

Scan results without a cache server (vulnerability found)

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

Scan results when a cache server is used (vulnerability not found)

Виявлення SQL-ін’єкцій на основі часу

Для пошуку таких вразливостей можна використовувати платформу Invicti (на основі Acunetix та Netsparker), яка знаходить велику кількість складних недоліків, подібних до цього.

Щоб безкоштовно протестувати це рішення, залиште ваші контактні дані нижче, і ми з вами зв’яжемося:

Запит на безкоштовне тестування Invicti

Підписатися на новини