Django SQL注入历史漏洞分析
字数 1714 2025-08-27 12:33:37
Django SQL注入历史漏洞分析教学文档
前言
本文档详细分析Django框架中三个重要的SQL注入历史漏洞:CVE-2020-7471、CVE-2021-35042和CVE-2022-28346。这些漏洞涉及Django的不同版本和组件,通过分析这些漏洞可以帮助开发者理解Django的安全机制和防范SQL注入的最佳实践。
CVE-2020-7471: StringAgg分隔符注入
漏洞概述
- 影响版本:Django 1.11.x < 1.11.28, 2.2.x < 2.2.10, 3.0.x < 3.0.3
- 漏洞位置:
contrib.postgres.aggregates.StringAgg聚合函数的delimiter参数 - 漏洞描述:当使用不受信任的数据作为StringAgg的分隔符时,攻击者可构造恶意分隔符绕过转义机制,注入SQL代码
漏洞分析
- StringAgg函数:将输入值使用指定分隔符连接起来
- 漏洞点:分隔符参数未经过适当转义直接嵌入SQL语句
- PoC验证:
- 当分隔符为单引号时,SQL语句会报错,显示未转义的单引号
- 构造payload:
')--可注释掉后续SQL语句
漏洞利用
# 构造恶意查询
results = Info.objects.all().values('gender').annotate(
mydefinedname=StringAgg('name', delimiter="')--")
)
修复方案
官方通过引入django.db.models.Value来防御:
delimiter_expr = Value(str(delimiter))
Value函数会将参数加入sql parameter list,经过Django内置过滤机制处理
CVE-2021-35042: order_by()注入
漏洞概述
- 影响版本:Django 3.1.x < 3.1.13, 3.2.x < 3.2.5
- 漏洞位置:
QuerySet.order_by()方法 - 漏洞描述:当order_by参数来自不可信的客户端输入时,攻击者可构造恶意输入进行SQL注入
漏洞分析
- order_by处理流程:
- 调用
clear_ordering()清除原有排序 - 调用
add_ordering()添加新排序条件
- 调用
- 关键漏洞点:
- 带点号(.)的字段名会跳过列名有效性检查
get_order_by()函数中列名部分未经过滤
漏洞利用
# 恶意请求示例
User.objects.order_by("app_user.name);select updatexml(1, concat(0x7e,(select @@version)),1)#")
修复方案
- 严格验证order_by参数
- 对列名部分也进行过滤处理
CVE-2022-28346: annotate/aggregate/extra别名注入
漏洞概述
- 影响版本:Django 2.2.x < 2.2.28, 3.2.x < 3.2.13, 4.0.x < 4.0.4
- 漏洞位置:
QuerySet.annotate(),aggregate(),extra()方法 - 漏洞描述:当使用字典展开(**kwargs)传递列别名时,恶意构造的字典可导致SQL注入
漏洞分析
- 处理流程:
annotate()调用_annotate并传入kwargs- 将kwargs更新到annotations中
- 遍历annotations调用
add_annotation
- 漏洞点:
- 在
resolve_expression解析过程中未对聚合参数进行充分检查 - 别名部分可直接注入SQL代码
- 在
修复方案
- 严格验证annotate/aggregate/extra的kwargs参数
- 对列别名进行转义处理
总结与防御建议
漏洞共性
- 都涉及Django ORM中参数处理不严谨
- 都允许通过精心构造的参数注入SQL代码
- 都影响多个Django版本
防御措施
- 及时更新:保持Django版本为最新安全版本
- 输入验证:
- 对所有用户提供的参数进行严格验证
- 使用Django提供的安全函数(如Value)处理参数
- 最小权限原则:数据库连接使用最小必要权限
- 安全编码实践:
- 避免直接拼接用户输入到查询中
- 使用参数化查询
- 对特殊字符进行转义
开发者检查清单
- 检查项目中是否使用了受影响版本的Django
- 审查代码中是否直接使用用户输入作为查询参数
- 确保所有动态查询都使用Django的安全机制处理
- 对关键业务功能进行安全测试
通过深入理解这些漏洞的原理和修复方案,开发者可以更好地编写安全的Django应用程序,避免类似的SQL注入风险。