# 단 20MB HTTP 패킷으로 Django 서버를 1분간 먹통 만드는 취약점이 공개되었습니다 (CVE-2026-33033)

> Clean Markdown view of GeekNews topic #28512. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=28512](https://news.hada.io/topic?id=28512)
- GeekNews Markdown: [https://news.hada.io/topic/28512.md](https://news.hada.io/topic/28512.md)
- Type: news
- Author: [nuremberg](https://news.hada.io/@nuremberg)
- Published: 2026-04-14T15:58:53+09:00
- Updated: 2026-04-14T15:58:53+09:00
- Original source: [new-blog.ch4n3.kr](https://new-blog.ch4n3.kr/django-pre-auth-denial-of-service-kr/)
- Points: 11
- Comments: 4

## Topic Body

**전체 한 줄 요약**  
  
Django의 `MultiPartParser`에서 `Content-Transfer-Encoding: base64` 파트 본문이 공백 위주일 때 발생하는 Pre-Auth CPU exhaustion 취약점으로, 약 2.5MB 요청 하나로 정상 대비 2,100배 이상의 처리 시간을 유발함 (CVE-2026-33033)  
  
  
**요약**  
  
  
- 인증 없이, 기본 설정 서버에서도 트리거 가능  
  - CSRF 미들웨어가 view 진입 전 request.POST에 접근하면서 MultiPartParser를 자동 실행하기 때문에, 인증된 엔드포인트라도 CSRF 검증 단계에서 이미 수초가 소요됨  
- 20MB 요청 하나로 단일 worker를 약 1분간 점유  
  - 4~16개 worker로 운영하는 일반적인 gunicorn 설정이라면 동시 수십 개 요청만으로 서버가 사실상 마비됨  
  
* Django는 `multipart/form-data` 요청을 `MultiPartParser`가 처리하며, CSRF 미들웨어가 view 진입 전에 `request.POST`에 접근하기 때문에 인증 없이도 이 파서가 항상 실행됨  
* 취약점의 핵심은 세 레이어가 곱해지는 구조임  
  * (Layer 1) base64 정렬 while-loop: 청크를 공백 제거하면 `remaining != 0` 상태가 유지되어 `field_stream.read(1)` 이 이후 스트림 전체에 대해 반복 호출됨  
  * (Layer 2) `LazyStream.read(1)` 의 숨겨진 O(C) 비용: `read(1)` 한 번 호출 시 내부적으로 ~64KB 버퍼를 통째로 꺼냈다가 65,535바이트를 `unget()`으로 도로 밀어넣는 패턴이 반복됨  
  * (Layer 3) `unget()`의 O(C) bytes concatenation: `bytes + self._leftover` 라는 새 객체 생성이 매번 발생  
* **2.5MB 요청 하나가 내부적으로 약 86GB 메모리 복사를 유발**하며, M2 기준 약 5.3초간 worker 하나를 완전히 점유함. 20MB에서는 약 1분 소요  
* `unget()` 내부에 이미 sanity check 코드(`_update_unget_history`)가 존재했지만, 이번 공격은 `unget()` 사이즈가 매 호출마다 1씩 감소하는 단조감소 패턴이라 탐지 조건(`number_equal > 40`)을 절대 충족하지 않음  
* Django 팀의 패치 핵심은 `read(4 - remaining)` → `read(self._chunk_size)`로, 1~3바이트씩 읽는 대신 한 번에 64KB씩 읽도록 변경. 이로써 read 호출이 250만 번 → 약 40번으로 감소  
* Nginx `client_max_body_size` 기본값은 1MB이지만 파일 업로드 엔드포인트에서는 완화되는 경우가 흔하고, Apache httpd의 `LimitRequestBody` 기본값은 1GB이므로 프록시만으로는 방어가 보장되지 않음  
* Claude Code + Codex를 활용해 발견한 취약점으로, 약 20년 가까이 다듬어진 프레임워크에서 Pre-Auth DoS가 남아있었다는 점이 인상적

## Comments



### Comment 55488

- Author: kalista22
- Created: 2026-04-15T18:01:47+09:00
- Points: 1

가즈아ㅏㅏ

### Comment 55433

- Author: tangokorea
- Created: 2026-04-15T14:59:37+09:00
- Points: 1

이거 직접 해보신 분 손?

### Comment 55435

- Author: nuremberg
- Created: 2026-04-15T15:05:37+09:00
- Points: 1
- Parent comment: 55433
- Depth: 1

데모용으로 만든 PoC가 GitHub에 올라와있습니다.  
  
https://github.com/ch4n3-yoon/CVE-2026-33033-PoC

### Comment 55439

- Author: tangokorea
- Created: 2026-04-15T15:11:45+09:00
- Points: 1
- Parent comment: 55435
- Depth: 2

따봉입니다.
