11 poin oleh nuremberg 6 hari lalu | 4 komentar | Bagikan ke WhatsApp

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.POST sebelum masuk ke view, MultiPartParser otomatis dijalankan; akibatnya, bahkan endpoint yang memerlukan autentikasi pun sudah menghabiskan beberapa detik pada tahap verifikasi CSRF
  • 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-data dengan MultiPartParser, dan karena middleware CSRF mengakses request.POST sebelum 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 != 0 tetap bertahan sehingga field_stream.read(1) terus dipanggil berulang untuk seluruh sisa stream
    • (Layer 2) biaya tersembunyi O(C) pada LazyStream.read(1): setiap satu kali pemanggilan read(1), secara internal buffer ~64KB diambil utuh lalu 65,535 byte didorong kembali dengan unget() secara berulang
    • (Layer 3) konkatenasi bytes O(C) pada unget(): objek baru bytes + self._leftover dibuat setiap kali
  • 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 ukuran unget() 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_size adalah 1MB, tetapi pada endpoint upload file batas ini sering dilonggarkan, dan nilai default LimitRequestBody di 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

 
kalista22 5 hari lalu

Mantappp

 
tangokorea 5 hari lalu

Ada yang pernah coba langsung ini?

 
nuremberg 5 hari lalu

PoC yang dibuat untuk demo telah diunggah ke GitHub.

https://github.com/ch4n3-yoon/CVE-2026-33033-PoC

 
tangokorea 5 hari lalu

Mantap.