Pada tanggal 7 Oktober 2019, direktur penelitian di PortSwigger (produsen BurpSuite) menerbitkan penelitian tentang pendekatan baru untuk penyelundupan Permintaan HTTP. Dengan bantuan mereka, dia menghasilkan sekitar $ 70.000 di bugbounty. Pada artikel ini, kami secara singkat mengetahui inti dari serangan, alat, dan juga metode meneliti server web yang rentan terhadap kerentanan ini.
Apa itu Penyelundupan Permintaan HTTP
Penyelundupan Permintaan HTTP - serangan yang ditujukan untuk menyinkronkan frontend server web dan backend server web, sebagai akibatnya penyerang dapat menyelundupkan permintaan HTTP melewati server frontend. Gambar dari artikel asli berfungsi sebagai demonstrasi yang bagus:

Serangan semacam itu dapat menyebabkan berbagai konsekuensi - pengenalan XSS di sesi pengguna lain, mengarahkan pengguna ke sumber daya pihak ketiga, meracuni cache server, kemiripan dengan SSRF, dan sejumlah lainnya.
Dalam Penjelmaan Penyelundupan 2019 tahun 2019, James Kettle mengeksploitasi pemrosesan header server web yang salah
Transfer-Encoding: chunked
menunjukkan bahwa isi pesan akan dikirim dalam bagian ( RFC ). Karena beberapa server web tidak mendukung transmisi yang terpotong, atau menangani tajuk secara berbeda, frontend akan “melihat” hanya satu permintaan, dan backend akan mengenalinya sebagai dua. Rincian lebih lanjut tentang rincian serangan dapat ditemukan di artikel asli , ada juga tugas praktis di mana Anda dapat berlatih untuk menemukan kerentanan secara manual.
Untuk pencarian cepat, James mengembangkan plug-in untuk BurpSuit, yang menerima permintaan untuk input dan membuat catatan tentang kerentanan layanan (jika ada) di output.
Contoh server web yang rentan
Saya harus mengatakan bahwa masalah penyelundupan dan kerentanan lainnya yang terkait dengan pengoperasian server web telah lama ditangani oleh peneliti lain dengan nama panggilan regilero . Selama tiga tahun terakhir, ia telah menerbitkan tiga artikel yang menggambarkan kerentanan yang ia temukan di server web populer, yang sebagian besar ditugaskan CVE dengan tingkat kekritisan sedang dan tinggi. Di antara server yang rentan adalah Apache Traffic Server, Jetty, Apsis.
Setelah tertarik pada masalah ini, peneliti lain, Nathan Davison, menemukan kerentanan di HAProxy, yang mengabaikan header yang salah bentuk.
Transfer-Encoding:[\x0b]chunked
dan mengubahnya menjadi bentuk berikut:
Transfer-Encoding: chunked
Tapi server backend - gunicorn, proksi aplikasi pada Flask, baca header, yang memancing kerentanan.
Beberapa saat kemudian, sejumlah peneliti lain menemukan kerentanan (ditugaskan CVE-2019-16276) dalam implementasi server http golang - server menormalkan header jika ada ruang sebelum tanduk.
Minta:

Setelah diproses oleh server:

Kerentanan dapat dieksploitasi jika server frontend mengabaikan header dengan spasi, dan menggunakan Content-Length untuk menghitung ukuran permintaan.
Server web Caddy yang ditulis dalam Go juga rentan karena menggunakan pustaka net / http yang sama. Pengembang mengkonfirmasi bahwa setelah memperbarui GO dan membangun kembali paket, masalahnya hilang.
Penulis artikel ini menemukan masalah serupa di server lighthttpd (tidak ada CVE yang ditugaskan). Tangkapan layar menunjukkan bahwa server menerima dan memproses tajuk yang berisi spasi:

Pengembang tidak cukup setuju dengan RFC 7230 (dan penulis juga), dan percaya bahwa tanggung jawab untuk pemrosesan header yang salah terletak pada proksi yang meneruskan permintaan tanpa menormalkan dan memeriksanya. Namun, bug akan diperbaiki pada rilis baru:
Secara default, lighttpd mem-parsing (dan menormalkan) permintaan sebelum mem-reverse-proxy ke backend Melakukan hal itu menggagalkan serangan yang disebutkan di https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn ke server di hulu dari lighttpd.
Namun, seperti yang disebutkan oleh stbuehler di atas, proksi downstream dari lighttpd mungkin meneruskan apa saja ke lighttpd.
Perubahan yang akan dilakukan pada rilis lighttpd berikutnya adalah menolak permintaan dengan spasi atau tab setelah nama-bidang dan sebelum titik dua, tetapi hanya ketika lighttpd dikonfigurasi dalam mode (default) mode parsing header http ketat.
Bug yang sama ditemukan di server web cheroot yang digunakan oleh kerangka kerja cherrypy. Kerangka kerja mini ini ditemukan di startup, sering digunakan untuk menulis API. Laporan bug tergantung pada status yang dibuka.
Diperlukan dan kondisi yang cukup untuk kerentanan
Jadi, apa kondisi yang diperlukan untuk memeriksa dan mengeksploitasi kerentanan:
- Permintaan POST. Meskipun RFC tidak secara eksplisit melarang penggunaan header Content-Length dan Transfer-Encoding untuk permintaan GET, pada kenyataannya mereka hanya digunakan dalam permintaan POST.
- Kehadiran server frontend dan backend - jika tidak ada, tidak akan ada yang disinkronkan.
- Server web harus menguraikan header Transfer-Encoding secara berbeda, yaitu, seseorang harus "membacanya", dan yang kedua harus diabaikan.
Pengujian laboratorium
Untuk pemahaman dan pemecahan masalah yang lebih baik di server web dan proksi yang ada, sebaiknya gunakan lingkungan pengujian secara lokal menggunakan Docker.
Contoh diagram lingkungan pengujian:

Kode Aplikasi:
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def main(): # the next line is required for Transfer-Encoding support in the request request.environ['wsgi.input_terminated'] = True headers = {} for header in request.headers: headers[header[0]] = header[1] print (request.data) print (headers) return jsonify(body=str(request.data), headers=headers)
File dengan pengaturan frontend, misalnya, caddy:
localhost:80 log ../access.log proxy / host.docker.internal:8888
Maka semuanya sederhana, jalankan aplikasi:
gunicorn --keep-alive 10 -k gevent --bind 0.0.0.0:8888 -w 4 backend:app
Dan wadah:
docker run -d -t --name caddy -p 80:80 -p 443:443 -v /Users/sun/work/caddyfile:/etc/Caddyfile abiosoft/caddy:latest
Dari toko Burp kami menginstal Permintaan HTTP Smuggler dan Logger ++ untuk kenyamanan debugging. Selanjutnya di Repeater kami membentuk permintaan sederhana, misalnya ini:
POST / HTTP/1.1 Host: localhost Content-Length: 8 Connection: close body=123
Dan kirimkan untuk memeriksa apakah semuanya sudah terkonfigurasi dengan benar:
HTTP/1.1 200 OK Content-Length: 202 Content-Type: application/json Date: Mon, 07 Oct 2019 13:17:18 GMT Server: Caddy Server: gunicorn/19.9.0 Connection: close {"body":"b'body=123'","headers":{"Accept-Encoding":"gzip","Connection":"close","Content-Length":"8","Host":"host.docker.internal:8888","User-Agent":"Go-http-client/1.1","X-Forwarded-For":"172.17.0.1"}}
Sekarang luncurkan Launch Smuggle Probe dan lihat jawabannya.

Yang paling menarik dimulai pada saat ini. Penting untuk menganalisis permintaan dan tanggapan untuk memahami apakah layanan rentan atau tidak. Bagian ini dibiarkan bagi pembaca yang ingin tahu.