Django的filter()、get()等方法底层使用参数化查询,用户输入仅作为绑定参数传入,绝不会拼接进SQL字符串,因此对值层面SQL注入天然免疫;但动态字段名、raw()/extra()中的SQL结构、order_by()等仍需白名单校验或严格使用params传参。

Django ORM 对用户输入的“值”天然免疫 SQL 注入,但字段名、排序字段、raw() 中的 SQL 结构部分仍需手动防护;XSS 方面,模板默认对 {{ }} 变量做 HTML 转义,但 |safe、mark_safe()、JS 上下文或属性值中插入用户数据时会绕过防护。
filter() 和 get() 为什么不会被 SQL 注入?
Django 的 filter()、get()、exclude() 等 QuerySet 方法底层全部走参数化查询(如 PostgreSQL 的 %s 占位符 + 绑定参数),用户输入只作为参数传入,绝不会拼进 SQL 字符串里。
- 即使传入
"admin' OR 1=1 --"这样的字符串,也会被当作普通值查,不会改变语义 - 不安全写法只出现在你主动跳出 ORM:比如用
connection.cursor().execute()或extra()拼字符串 -
filter(**{field_name: value})是高危模式——field_name是字典 key,Django 不转义它,攻击者可传"__class__"或"id__in"触发非预期行为
raw() 和 extra() 怎么用才不踩坑?
raw() 和 extra() 完全跳过 ORM 编译器,SQL 字符串由你全权负责。一旦拼接用户输入,防护即失效。
- 错误:
User.objects.raw("SELECT * FROM auth_user WHERE username = '" + request.GET.get('q') + "'") - 正确:
User.objects.raw("SELECT * FROM auth_user WHERE username = %s", [request.GET.get('q')]) -
extra(where=["status = %s"], params=[status_val])✅;extra(where=[f"status = '{status_val}'"])❌ - MySQL/SQLite 只支持位置占位符
%s;PostgreSQL 支持%(name)s,但混用会导致运行时报错 -
params必须是list或tuple,顺序必须与 SQL 中占位符出现顺序严格一致
模板里哪些地方会漏防 XSS?
Django 模板默认对 {{ user_input }} 做 HTML 转义,但以下场景会直接输出原始内容,必须额外处理:
立即学习“Python免费学习笔记(深入)”;
- 用了
|safe过滤器:{{ user_input|safe }}—— 此时你得确保user_input已过滤或来自可信源 - 调用
mark_safe():mark_safe(request.GET.get('html'))—— 同样绕过转义 - 在 JS 字符串中插值:
<script>var name = "{{ user_name }}";</script>——"和\未被 JS 转义,应改用json_script或escapejs过滤器 - 在 HTML 属性里插值:
<div data-id="{{ user_id }}"></div>—— 若user_id含双引号或>,可能破坏结构,推荐用escape或严格校验格式
动态字段名和 order_by() 怎么校验?
所有接收字符串字段名的 ORM 方法(order_by()、values()、annotate() 中的 F()、RawSQL 的字段引用)都不做白名单检查,必须人工拦截。
- 禁止直接使用:
Article.objects.order_by(request.GET.get('sort')) - 应先白名单比对:
if sort_field not in ["title", "-created_at", "author__name"]: raise Http404() - 更稳妥的方式是建立映射表:
{"title": "title", "date": "-created_at"},再取值 -
__regex、__search等特殊 lookup 的参数也属“值”范畴,ORM 会参数化,但正则模式本身若不可控,可能引发 ReDoS,需长度和字符集限制
最常被忽略的是:ORM 的安全机制只覆盖“值”,不覆盖 SQL 结构;而模板的转义只覆盖 HTML 文本上下文,不覆盖 JS、CSS、URL 或属性值。这两类边界一旦模糊,漏洞就藏在看似“已防护”的地方。


















