sql盲注和xss防护必须严格遵循参数化查询与上下文敏感转义:sql所有查询须用参数化(如cursor.execute("where id = %s", (id,))或orm过滤;动态排序/列名需白名单校验;xss中jinja2默认转义有效,但|safe、js上下文须用|tojson、属性值用|e,富文本须bleach.clean()白名单过滤,前端禁止拼接html或url。

SQL盲注和XSS不是“能防住就行”的问题,而是只要漏掉一个参数化、一处|safe、一个动态ORDER BY字段,整条防线就崩塌。
SQL盲注:布尔/时间延迟型攻击只认参数化,不认类型校验
盲注不依赖错误回显,所以RequestParser把id转成int、甚至加了min=1, max=999999,都拦不住攻击者用1 AND SLEEP(5)或1 AND (SELECT SUBSTR(password,1,1) FROM users WHERE id=1)='a'来逐字猜解——因为这些 payload 仍能通过类型校验(比如SLEEP(5)在MySQL里返回0,是合法整数)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 所有数据库查询必须走参数化:用
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)),或 SQLAlchemy 的filter(User.id == user_id);f"WHERE id = {user_id}"、"WHERE id = %s" % user_id、.format()全算违规 -
text()原生 SQL 是高危区:必须用命名占位符:name,且第二参数只能是字典,如session.execute(text("SELECT * FROM users WHERE name = :name"), {"name": name});?name或%s在text()里无效 - 动态排序/列名无法参数化:协议层禁止。必须白名单校验:
if sort_field not in ["id", "created_at"]: raise ValueError("Invalid sort");别信replace(";", "")或正则删--,十六进制编码可绕过
XSS:Jinja2自动转义只保HTML上下文,JS和属性值要另设防线
{{ user_input }}默认安全,但一旦写成{{ user_input|safe }},等于主动交出控制权——哪怕只是调试时临时加的,上线就变后门。
- JS上下文必须用
|tojson:<script>var data = {{ user_input | tojson }};</script>;写成"{{ user_input }}"会因单引号、反斜杠破坏语法,触发执行 - 属性值用单引号包裹 +
|e:<div id="{{ user_id | e }}"> ;双引号属性里插<code>"或=照样能闭合标签并注入 - 富文本不能靠
|safe放行:必须用bleach.clean()清洗,只允许['p', 'a', 'strong']等白名单标签,禁用onerror、javascript:、data:伪协议 - 绝对不拼HTML字符串:
f"<div>{name}</div>"绕过Jinja2全部防护;视图函数只传原始数据,渲染全交给模板
最容易被忽略的交叉点:前端JS拿到后端数据后二次拼接
后端用|tojson传了干净数据,但前端写location.href = "/user?id=" + data.id,或el.innerHTML = data.content,等于把XSS漏洞从服务端搬到了客户端。DOMPurify.sanitize()是补救,不是替代;真正该做的是用textContent、dataset属性、URL构造器等上下文感知方式处理用户数据。










