HTTP Request Smuggling Berawal dari Perbedaan Framing Pesan
Reverse proxy dapat memvalidasi request HTTP, meneruskannya ke aplikasi yang diizinkan, tetapi tetap mengirim urutan request yang berbeda dari yang dianggapnya telah diterima. Kegagalan ini tidak mengharuskan proxy mengabaikan autentikasi atau origin menjalankan sintaks yang rusak. Masalah dapat muncul ketika dua pemroses HTTP berbeda pendapat tentang byte yang menandai akhir satu request dan awal request berikutnya.
Perbedaan itulah batas keamanan utama pada HTTP request smuggling. Front end membaca stream dengan satu interpretasi framing, sedangkan penerima downstream membaca stream yang diteruskan dengan interpretasi lain. Byte yang dianggap body oleh satu komponen dapat dianggap awal request baru oleh komponen lain. Pada koneksi persisten, interpretasi kedua dapat memengaruhi trafik yang datang kemudian pada channel downstream yang sama.
Jadi, kerentanan ini bukan sifat satu header mencurigakan secara terpisah. Ini adalah kegagalan komposisi antara parser, aturan normalisasi, konversi protokol, dan penggunaan ulang koneksi.
Framing pesan menentukan kepemilikan setiap byte
HTTP/1.1 menjalankan banyak pesan melalui satu koneksi, sehingga setiap penerima memerlukan aturan jelas untuk menemukan batas pesan. Untuk request, keberadaan dan panjang body ditentukan oleh field framing seperti Content-Length dan Transfer-Encoding, sesuai aturan precedence dan validitas RFC 9112.
Content-Length yang valid menyatakan jumlah octet body dalam desimal ketika Transfer-Encoding tidak ada. Transfer coding chunked mengakhiri body melalui sintaks chunk. RFC 9112 memberi Transfer-Encoding precedence jika keduanya ada, mengaitkan kombinasi tersebut dengan risiko request smuggling, dan mengizinkan server menolak request. Intermediary yang meneruskannya harus menghapus Content-Length setelah memproses transfer coding.
Aturan ini ada karena kesalahan batas dapat menyebar melewati request saat ini:
[request A headers][request A body][request B headers][request B body]Jika front end menempatkan akhir request A setelah byte 600 tetapi origin menempatkannya setelah byte 480, byte 481 hingga 600 tidak lagi memiliki kepemilikan yang sama. Front end menganggapnya body; origin dapat menganggap sebagian byte tersebut awal request HTTP lain.
Autentikasi terhadap request A versi front end tidak otomatis menjelaskan urutan yang direkonstruksi origin.
Kesepakatan parser lebih penting daripada kelonggaran parser
Parsing longgar belum tentu dapat dieksploitasi jika semua komponen membuat keputusan yang sama. Kondisi berbahaya adalah parsing yang berbeda di sepanjang chain.
RFC 9112 memperingatkan bahwa perlakuan permisif terhadap whitespace request-line dapat menimbulkan risiko ketika penerima berbeda memakai interpretasi berbeda. Kekhawatiran yang sama berlaku untuk framing: perilaku robustness di satu hop menjadi masalah keamanan ketika hop berikutnya mengenali grammar atau precedence lain.
CDN, load balancer, service mesh proxy, application gateway, dan origin masing-masing dapat mem-parse atau membuat ulang HTTP. Request tidak aman hanya karena setiap parser konsisten secara lokal. Setiap transisi harus menghasilkan satu pesan downstream canonical yang batasnya tidak dapat ditafsirkan ulang.
Memblokir satu bentuk teks Transfer-Encoding juga tidak membuktikan adanya kesepakatan framing. Komponen lain dapat menormalkan nama field, menggabungkan duplicate field, menerima sintaks berbeda, atau menerapkan aturan berbeda setelah konversi protokol. Tujuan keamanan adalah konstruksi pesan yang deterministik, bukan daftar pola byte yang terus bertambah.
Sinyal panjang yang bertentangan harus ditangani fail-closed
Request yang memuat Transfer-Encoding dan Content-Length membawa sinyal panjang yang bersaing. Spesifikasi HTTP/1.1 modern menentukan precedence, tetapi menerima dan meneruskan trafik seperti ini tetap berbahaya jika chain downstream tidak dijamin memakai aturan sama.
Batas yang lebih aman adalah menolak atau menormalkan sepenuhnya sebelum forwarding. Normalisasi lengkap berarti intermediary mem-parse pesan dengan policy ketat, memperoleh content aktual, lalu membuat pesan downstream baru tanpa mempertahankan metadata framing yang bertentangan.
Meneruskan kedua field apa adanya mempertahankan ambiguitas. Menghapus field berdasarkan pemeriksaan teks dangkal juga tidak cukup jika layer lain sudah mem-parsingnya secara berbeda.
Duplicate Content-Length memiliki batasannya sendiri. RFC 9112 menganggap Content-Length tidak valid sebagai error framing yang tidak dapat dipulihkan, dengan pengecualian sempit untuk daftar comma-separated yang seluruh nilainya valid dan identik. Nilai berbeda bukan pilihan panjang yang sah.
Reuse koneksi memperluas dampak perbedaan
Mismatch framing menjadi lebih serius ketika front end memakai ulang satu koneksi HTTP/1.1 downstream untuk request dari banyak client.
Front end mungkin menganggap seluruh byte request penyerang sudah dikonsumsi dan meneruskannya. Origin berhenti lebih awal dan menyimpan byte tambahan di buffer. Saat front end meneruskan request client lain pada koneksi yang sama, origin dapat memproses byte yang tersimpan lebih dahulu atau menggabungkan state stream dalam urutan yang tidak dimaksudkan front end.
Dampaknya bergantung pada perbedaan parser dan perilaku aplikasi. Kemungkinannya meliputi kebingungan routing, gangguan cache, mismatch konteks authorization, atau respons yang dikaitkan dengan transaksi front end yang salah. Dampak tersebut memerlukan jalur desinkronisasi konkret; tidak setiap field length yang rusak otomatis menyebabkan account compromise atau cache poisoning.
Koneksi backend khusus dapat mengurangi dampak lintas pengguna pada arsitektur tertentu, tetapi tidak memperbaiki perbedaan parser itu sendiri.
HTTP/2 menghapus chunk framing, bukan semua risiko konversi
HTTP/2 membingkai isi pesan secara eksplisit dan tidak memakai chunked transfer coding HTTP/1.1. RFC 9113 juga menyatakan pesan malformed jika nilai content-length tidak sama dengan jumlah payload DATA frame, kecuali pesan yang memang tidak memiliki content.
Desain ini menghapus sumber ambiguitas penting pada hop HTTP/2 native, tetapi arsitektur campuran tetap dapat mengalami desinkronisasi. Gateway yang menerima HTTP/2 lalu membuat HTTP/1.1 untuk origin bertanggung jawab membangun framing HTTP/1.1 yang valid. Sebaliknya, intermediary yang menerima HTTP/1.1 harus menyelesaikan framing sebelum membuat HTTP/2 frame.
Konversi protokol adalah batas parser sekaligus batas konstruksi pesan. Ambiguitas HTTP/1.1 tidak hilang hanya karena representasinya berubah.
Normalisasi header dapat mengubah permukaan parser
Pemrosesan field HTTP dapat mencakup lowercasing nama, penggabungan repeated field, trimming whitespace yang diizinkan, penghapusan hop-by-hop field, atau pemetaan ke format wire baru. Transformasi ini menjadi penting jika terjadi sebelum atau sesudah tahap validasi berbeda.
Validator yang memeriksa raw byte dapat mengambil keputusan berbeda dari library HTTP yang memproses field ternormalisasi. Chain yang kuat mengikat validasi framing pada parser yang menentukan batas pesan, lalu melakukan forwarding dari representasi yang sudah diterima, bukan dari byte asli yang hanya difilter sebagian.
Setiap trust boundary memerlukan kontrak jelas: input malformed atau ambigu ditolak, content yang diterima memiliki satu panjang, dan serialisasi downstream tidak dapat memperkenalkan delimiter yang bersaing.
Pengujian harus mencakup seluruh urutan hop
Menguji parser origin saja tidak cukup karena request smuggling bersifat relasional. Target pengujian adalah urutan front end, intermediary, konversi protokol, dan origin yang benar-benar digunakan.
Uji apakah satu input dapat membuat komponen berbeda pendapat tentang jumlah atau batas pesan. Sertakan konflik framing, duplicate length, sintaks transfer-coding malformed, whitespace tidak biasa, dan perilaku konversi protokol.
Hasil aman bukan harus berupa teks error yang sama di setiap layer. Satu layer boleh menolak lebih awal. Invariannya adalah input ambigu tidak meninggalkan state koneksi downstream yang dapat diwarisi request berikutnya.
Framing ketat mengubah ambiguitas menjadi kegagalan lokal
Request smuggling melewati trust boundary ketika satu pemroses menerima byte yang kepemilikannya berubah pada pemroses berikutnya. Kontrol yang tahan lama adalah mencegah kepemilikan ambigu bertahan melewati boundary tersebut.
Parsing ketat mempersempit grammar. Penolakan framing yang bertentangan mencegah tebakan. Reserialisasi canonical menghapus metadata lama setelah parsing. Protocol converter harus membuat framing yang valid untuk protokol tujuan, dan koneksi persisten sebaiknya ditutup ketika error framing membuat residual buffered state tidak aman.
Kontrol ini tidak bergantung pada tebakan payload penyerang. Properti yang lebih kuat adalah: setelah intermediary menerima dan meneruskan request, penerima downstream memperoleh tepat satu batas pesan yang sesuai dengan request yang diterima. Keamanan berasal dari kesepakatan parser pada batas komposisi, bukan dari keyakinan bahwa satu parser cukup ketat secara terpisah.