Уявіть двох кухарів на кухні, які одночасно простягаються до одного й того самого інгредієнта, що спричиняє катастрофу в рецепті. Це умова гонки в цифровому світі — дефект, коли невірний час дій призводить до хаосу і вразливостей. Давайте розглянемо, що це таке і чому це важливо.
Відправка кількох запитів до сервера одночасно може призвести до серйозних вразливостей у безпеці, більших, ніж ми могли б очікувати. Коли веб-застосунок не може належним чином обробляти запити паралельно, це може спричинити зіткнення кількох різних потоків, що одночасно взаємодіють з одними й тими самими даними, що призводить до небажаної поведінки застосунку. Умова гонки — це техніка використання цієї вразливості для того, щоб скористатися непередбачуваними поведінками, які вона спричиняє.
Найпоширеніший приклад умови гонки — це поведінка промокодів на вебсайтах електронної комерції. Уявіть, що у вас є промокод. Коли ви використовуєте цей промокод, сервер зазвичай працює наступним чином:
- Перевіряє, чи був вже використаний цей промокод.
- Якщо код дійсний, застосовує знижку до суми замовлення.
- Оновлює базу даних, щоб зафіксувати, що код був використаний.
Після цього процесу, якщо ви спробуєте використати код знову, ви отримаєте помилку, звісно.
Але ось у чому справа! Що, якщо користувач спробує застосувати промокод двічі або кілька разів точно в один і той самий час?
Такий тип запиту створює маленьке вікно гонки, яке я можу повторити, щоб отримати знижку стільки разів, скільки захочу. У цьому вікні гонки, коли сервер намагається обробити запит вперше, він дозволяє нам використати знижку вдруге до того, як завершить перше, і наш бідний сервер затримується з оновленням інформації про використання промокоду. Вибачте, дитя.
Такі ситуації з умовами гонки зазвичай називаються "перевищенням ліміту". Проблеми з перевищенням ліміту виникають через проблему TOCTOU (від часу перевірки до часу використання), і такі ситуації можуть змінюватися в залежності від архітектури.
Виявити такі вразливості вручну може бути складно через точний час, необхідний для експлуатації вікон гонки. Тут на допомогу приходять інструменти, як-от Burp Suite. Burp Suite спрощує процес, дозволяючи створювати та відправляти одночасні запити в контрольованому середовищі, допомагаючи вам спостерігати, як застосунок поводиться під час цих критичних моментів. Після визначення цільової точки доступу, надсилання майже одночасних запитів за допомогою Burp Suite стає досить простим. Таким чином, ми можемо синхронізувати хоча б два вікна гонки (з мілісекундними відмінностями) і створити зіткнення. Тепер давайте докладніше розглянемо, як працюють вікна гонки, зокрема як інструменти можуть допомогти нам експлуатувати їх.
Хоча ми можемо спробувати вручну надіслати запити одночасно, різні зовнішні фактори, такі як латентність сервера і мережеві затримки, часто ускладнюють це. Щоб подолати ці труднощі, Burp Suite використовує техніки, такі як синхронізація останнього байта і атаки з одним пакетом, щоб точно контролювати час запитів, дозволяючи нам надіслати 20–30 запитів одночасно.
Коли запити відправляються через HTTP/1, Burp Suite Repeater використовує синхронізацію останнього байта. Це коли кілька запитів відправляються через одночасні з'єднання, але останній байт кожного запиту в групі затримується. Після короткої затримки ці останні байти надсилаються одночасно через кожне з'єднання.
Коли запити відправляються через HTTP/2+, Repeater відправляє групу, використовуючи атаку з одним пакетом.
Ось де кілька запитів надсилаються через один TCP-пакет.
Окрім техніки атаки з одним пакетом, для виявлення вразливостей в додатках можна також використовувати розширення Turbo Intruder. Для різних ситуацій з умовами гонки можуть знадобитися різні підходи; наприклад, поетапні та численні запити, динамічні введення та подібні випадки.
race-single-packet-attack.py
Що, якщо ми хочемо виконати вид атаки методом грубої сили, обминаючи обмеження швидкості через умову гонки?
Використання обмежень швидкості для входу з умовами гонки
Інший цікавий тип вразливості умов гонки може виникати в механізмах входу в систему, особливо в системах, які застосовують обмеження швидкості для блокування атак грубої сили. Хоча ці механізми призначені для підвищення безпеки, їх можна обійти, якщо використати умову гонки.
Уявіть, що ви експериментуєте з функцією входу веб-застосунку. Ви помічаєте, що якщо ви вводите неправильний пароль для свого облікового запису більше трьох разів, вас тимчасово блокують від подальших спроб увійти. Однак, якщо ви спробуєте увійти з іншим іменем користувача, ви все одно отримаєте звичайне повідомлення "Невірне ім'я користувача або пароль". Це свідчить, що обмеження швидкості застосовуються до кожного імені користувача, а не до сесії.
З цього ми можемо зробити висновок, що сервер зберігає кількість невдалих спроб входу для кожного імені користувача. Але що, якщо існує невелика тимчасова затримка між:
- Коли ви подаєте спробу входу.
- Коли вебсайт збільшує лічильник невдалих спроб входу?
Це вікно гонки — ось де можуть виникнути вразливості. Щоб дослідити це, ми можемо:
- Знайти невдалий запит на вхід у історії нашого проксі (щось на зразок
POST /login
). - Відправити цей запит до Repeater.
- Об'єднати вкладку Repeater і створити достатньо дублікатів.
- Надіслати ці запити послідовно, використовуючи окремі з'єднання, щоб спостерігати за поведінкою. Після двох невдалих спроб вас тимчасово заблокують, як і очікувалось.
Але що відбудеться, якщо ми відправимо ці запити паралельно, а не послідовно?
Коли ми надсилаємо одну й ту саму групу спроб входу паралельно, відбувається цікаве. Незважаючи на те, що обліковий запис заблокований після трьох невдалих спроб, кілька запитів все одно повертають звичне повідомлення "Невірне ім'я користувача або пароль". Це свідчить про те, що в межах вікна гонки сервер обробляє кілька спроб до того, як оновить лічильник невдалих спроб.
Ми можемо зайти ще далі, використовуючи Turbo Intruder:
- Виділіть параметр
password
у запитіPOST /login
і відправте його до Turbo Intruder.
2.
В редакторі Turbo Intruder використовуйте шаблонexamples/race-single-packet-attack.py
і змініть його наступним чином:
def queueRequests(target, wordlists):
# якщо ціль підтримує HTTP/2, використовуйте engine=Engine.BURP2 для запуску атаки з одним пакетом
# якщо підтримується лише HTTP/1, використовуйте Engine.THREADED або Engine.BURP замість цього
# для більш детальної інформації ознайомтесь з https://portswigger.net/research/smashing-the-state-machine
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# параметр 'gate' утримує частину кожного запиту, поки не буде викликано openGate
# якщо ви побачите негативний відміток часу, сервер відповів до того, як запит був завершений
for word in wordlists.clipboard:
engine.queue(target.req, word, gate='race1')
# після того, як кожен запит з міткою 'race1' буде поставлений у чергу
# викликаємо engine.openGate(), щоб надіслати їх синхронно
engine.openGate('race1')
def handleResponse(req, interesting):
table.add(req)
Тепер дійте! Якщо ви отримали щось на зразок відповіді 302, це означає, що один із запитів може обійти обмеження швидкості і успішно увійти.
Це був загальний огляд вразливостей умов гонки. Якщо ви хочете дізнатися більше і спробувати різні техніки, я додав кілька корисних ресурсів нижче.
Не хакіть сусідів і пийте достатньо води!
Джерела
[
Надсилання групових HTTP-запитів
Функція групового надсилання в Burp Repeater дозволяє надсилати групи HTTP-запитів одним кліком. Ви можете надіслати…
portswigger.net
](https://portswigger.net/burp/documentation/desktop/tools/repeater/send-group?source=post_page-----8825d7020397--------------------------------)
[
CWE - CWE-367: Час перевірки та використання (TOCTOU) Умови гонки (4.16)
Common Weakness Enumeration (CWE) — це список вразливостей програмного забезпечення.
cwe.mitre.org
](https://cwe.mitre.org/data/definitions/367?source=post_page-----8825d7020397--------------------------------)
[
Turbo Intruder
Надсилайте велику кількість HTTP-запитів і аналізуйте результати
portswigger.net
](https://portswigger.net/bappstore/9abaa233088242e8be252cd4ff534988?source=post_page-----8825d7020397--------------------------------)
[
GitHub - PortSwigger/turbo-intruder: Turbo Intruder — це розширення Burp Suite для надсилання великої кількості…
Turbo Intruder — це розширення Burp Suite для надсилання великої кількості HTTP-запитів і аналізу результатів. …
github.com
](https://github.com/portswigger/turbo-intruder?source=post_page-----8825d7020397--------------------------------)
[
Лабораторія: Обхід обмежень швидкості через умови гонки | Академія веб-безпеки
Механізм входу цієї лабораторії використовує обмеження швидкості для захисту від атак грубої сили. Однак їх можна обійти…
portswigger.net
](https://portswigger.net/web-security/race-conditions/lab-race-conditions-bypassing-rate-limits?source=post_page-----8825d7020397--------------------------------)
[
Зламування машини стану: справжній потенціал умов гонки в вебі
Надто довго атаки умов гонки в вебі фокусувалися на кількох сценаріях. Їх справжній потенціал…
portswigger.net
](https://portswigger.net/research/smashing-the-state-machine?source=post_page-----8825d7020397--------------------------------)
[
Зламування reCAPTCHA, стиль Turbo Intruder
Стомилися доводити, що ви не робот? У цьому пості я покажу, як частково обійти Google reCAPTCHA, використовуючи…
portswigger.net
](https://portswigger.net/research/cracking-recaptcha-turbo-intruder-style?source=post_page-----8825d7020397--------------------------------)
[
Умови гонки | Академія веб-безпеки
Умови гонки — це поширений тип вразливостей, тісно пов'язаний з помилками бізнес-логіки. Вони виникають, коли вебсайти…
portswigger.net
](https://portswigger.net/web-security/race-conditions?source=post_page-----8825d7020397--------------------------------)
Перекладено з: Race Conditions.