最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在Django项目中如何利用安全库规避SQL注入
时间:2026-07-08 10:43:57 编辑:袖梨 来源:一聚教程网
Django ORM原生防SQL注入仅限值层面,字段名、表名等结构参数须白名单校验;filter动态键名不转义,raw/extra必须用params传参且只认%s,RawSQL需手动参数化,优先用ORM原生表达式。
Django 本身不依赖外部“安全库”防 SQL 注入——它靠 ORM 的参数化机制原生防护,加白名单校验就能覆盖绝大多数场景;所谓“引入安全库”反而可能误导你忽略关键控制点。
filter() 动态字段名必须白名单校验
很多人把 request.GET.get('field') 直接塞进 filter(**{field_name: value}),以为 ORM 会自动过滤字段名。不会。Django 只绑定值,不校验键名。
- 攻击者传
is_staff__gt、_meta.model_name或password__contains就可能泄露敏感字段或触发越权查询 - 正确做法是先检查:if
field_name not in ['title', 'author__name', 'status'],再调用getattr(MyModel, field_name, None)确认字段真实存在且非property - 别用
Q("username = '{}'".format(u))拼字符串,改用Q(**{field_name + '__icontains': u})
raw() 和 extra() 必须用 params= 且只认 %s
raw() 和 extra() 是 ORM 中唯二允许写原生 SQL 的入口,也是注入高发区。它们不继承 filter() 的安全逻辑,拼字符串即失守。
-
raw()安全写法:User.objects.raw("SELECT * FROM auth_user WHERE username = %s", params=[username])——params必须是列表或元组,%s不能换成{}或%(name)s(SQLite 不支持命名参数) -
extra(where=["status = %s"], params=[u])是无效的:extra()的params参数被 Django 忽略,where字符串里不能含用户输入 - 真要动态条件,优先改用
Q+filter(),而不是硬塞进extra()
RawSQL 和 annotate() 中的 LIKE 必须手动转义
RawSQL 不自动参数化整个表达式,只对 params 对应的占位符生效。漏掉转义,% 和 _ 就会变成通配符,造成逻辑漏洞甚至拖垮数据库。
- 错误:
annotate(score=RawSQL(f"CASE WHEN title LIKE '%{search}%' THEN 1 ELSE 0 END")) - 正确:
RawSQL("CASE WHEN title LIKE %s THEN 1 ELSE 0 END", params=[f"%{search}%"]) - 更稳妥:
Case(When(title__icontains=search, then=1), output_field=IntegerField())—— ORM 原生表达式自动处理转义和索引优化 - 若必须用原生 LIKE,调用
connection.ops.prep_for_like_query(search)手动转义
最常被忽略的是结构参数:字段名、表名、ORDER BY、GROUP BY、函数名。这些都不走参数绑定,params= 粘不住。哪怕你 100% 没拼过 SQL 字符串,只要 order_by(request.GET.get('o')) 没白名单,就可能被用来触发全表扫描或暴露索引信息。
相关文章
- 王者荣耀世界东方曜与鲁班大师配队培养方法 07-08
- 鸣潮2.5:优化了哪些方面 07-08
- 星际裂变新手前期如何探索废墟 07-08
- 这城有良田威仪属性解析 07-08
- 指尖无双治安亭任务挑选攻略 07-08
- 《心动小镇》烹饪玩法技巧分享 07-08