别名 是 SQL 查询中给列或聚合结果起的名称。
在 Django 中,别名通过 annotate() 或 alias() 方法用于命名计算字段。
示例:
from django.db.models import Count
books = Book.objects.annotate(book_count=Count('id'))
这里,book_count 是 Count('id') 结果的别名。
这允许为计算列获取一个可读的名称。
为快速操作,可以通过 shell 插入数据:
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。
当使用带有未过滤用户提供的键的字典扩展 (**kwargs) 时,该漏洞会影响 annotate() 和 alias() 函数。
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) # 危险!允许执行任意代码
# 使用动态注解创建 queryset
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
日期: 2025年6月9日