CVE-2022-34265: Potential SQLi via Trunc() and Extract()

CVE-2022-34265: Potential SQLi via Trunc() and Extract()
The Cliff, Seven Sisters, England

개요

CVE-2022-34265: Potential SQL injection via Trunc(kind) and Extract(lookup_name) arguments

최근 우리 회사 슬랙 방에서 평소 존경하던 갓해커 분이 올려주신 Django SQL Injection CVE가 하나 있어서 분석해보았다. 아무래도 Django를 통해 사내 프로젝트, 학교 프로젝트를 몇 번씩 진행해본 경험이 있다보니 자칭 Django 전문가로서 CVE를 분석해보지 않고 지나칠 수가 없었다.

데모 소스코드를 보니 아래 부분에서 취약점이 발생했다. Extract와 Trunc에서 비슷한 이유로 취약점이 발생하는 듯 보였다.

print("[ INFO ] query :", ChallengeModel.objects.all().annotate(time=Trunc("created_at", "2020'")).query)
# [ INFO ] query : SELECT "challenge_challenge"."id", "challenge_challenge"."image_id", "challenge_challenge"."path", "challenge_challenge"."build_command", "challenge_challenge"."category_id", "challenge_challenge"."status", "challenge_challenge"."name", "challenge_challenge"."body", "challenge_challenge"."score", "challenge_challenge"."open_time", "challenge_challenge"."file", "challenge_challenge"."created_at", "challenge_challenge"."updated_at", django_datetime_trunc('2020'', "challenge_challenge"."created_at", 'UTC', 'UTC') AS "time" FROM "challenge_challenge"

이게 약간 무슨 느낌인지 PHP를 예시로 들어서 설명하자면 아래 코드와 같다.

그냥 $_REQUEST를 받을 때부터 md5로 해시처리하면 되는데 굳이 MySQL의 md5 함수 인자로 넣어 해시처리하는 느낌?

내가 만약 위와 같은 기능의 코드를 작성했다면 아래처럼 코드를 작성했을 것이다.

사용자로부터 date 값을 <str> 형태로 받고
Django의 timezone 오브젝트를 이용해 datetime 객체로 변환한 다음
Django ORM으로 QuerySet 질의

내일은 Trunc 클래스와 annotate 메소드를 분석해서 Django ORM에서 어떻게 QuerySet <-> Raw SQL Query를 구현했는지 찾아봐야겠다.