Kerentanan yang dapat melumpuhkan server Django selama 1 menit hanya dengan paket HTTP 20MB telah dipublikasikan (CVE-2026-33033)
(new-blog.ch4n3.kr)Ringkasan satu baris keseluruhan
Kerentanan pre-auth CPU exhaustion terjadi di MultiPartParser Django saat body part Content-Transfer-Encoding: base64 didominasi spasi, sehingga satu request sekitar 2.5MB dapat menyebabkan waktu pemrosesan lebih dari 2.100 kali dibanding normal (CVE-2026-33033)
Ringkasan
- Dapat dipicu tanpa autentikasi, bahkan pada server dengan konfigurasi default
- Karena middleware CSRF mengakses
request.POSTsebelum masuk ke view,MultiPartParserotomatis dijalankan; akibatnya, bahkan endpoint yang memerlukan autentikasi pun sudah menghabiskan beberapa detik pada tahap verifikasi CSRF
- Karena middleware CSRF mengakses
- Satu request 20MB dapat mengunci satu worker selama sekitar 1 menit
- Pada konfigurasi gunicorn umum dengan 4~16 worker, hanya dengan puluhan request bersamaan server secara praktis bisa lumpuh
- Django memproses request
multipart/form-datadenganMultiPartParser, dan karena middleware CSRF mengaksesrequest.POSTsebelum masuk ke view, parser ini selalu dijalankan bahkan tanpa autentikasi - Inti kerentanan adalah struktur di mana tiga layer saling mengalikan
- (Layer 1) while-loop penyelarasan base64: ketika spasi dihapus dari chunk, status
remaining != 0tetap bertahan sehinggafield_stream.read(1)terus dipanggil berulang untuk seluruh sisa stream - (Layer 2) biaya tersembunyi O(C) pada
LazyStream.read(1): setiap satu kali pemanggilanread(1), secara internal buffer ~64KB diambil utuh lalu 65,535 byte didorong kembali denganunget()secara berulang - (Layer 3) konkatenasi bytes O(C) pada
unget(): objek barubytes + self._leftoverdibuat setiap kali
- (Layer 1) while-loop penyelarasan base64: ketika spasi dihapus dari chunk, status
- Satu request 2.5MB secara internal memicu penyalinan memori sekitar 86GB, dan pada M2 menghabiskan satu worker sepenuhnya selama sekitar 5,3 detik. Pada 20MB, waktunya sekitar 1 menit
- Di dalam
unget()sebenarnya sudah ada kode sanity check (_update_unget_history), tetapi serangan ini menggunakan pola monotonic decrease di mana ukuranunget()berkurang 1 pada setiap panggilan, sehingga kondisi deteksi (number_equal > 40) tidak pernah terpenuhi - Inti patch dari tim Django adalah mengubah
read(4 - remaining)→read(self._chunk_size), sehingga alih-alih membaca 1~3 byte setiap kali, pembacaan dilakukan 64KB sekaligus. Dengan ini jumlah pemanggilan read berkurang dari 2,5 juta kali menjadi sekitar 40 kali - Nilai default Nginx
client_max_body_sizeadalah 1MB, tetapi pada endpoint upload file batas ini sering dilonggarkan, dan nilai defaultLimitRequestBodydi Apache httpd adalah 1GB, sehingga pertahanan hanya dengan proxy tidak menjamin perlindungan - Kerentanan ini ditemukan dengan memanfaatkan Claude Code + Codex, dan menarik bahwa pre-auth DoS masih tersisa di framework yang telah diasah hampir 20 tahun
4 komentar
Mantappp
Ada yang pernah coba langsung ini?
PoC yang dibuat untuk demo telah diunggah ke GitHub.
https://github.com/ch4n3-yoon/CVE-2026-33033-PoC
Mantap.