Flask不处理SQL注入,需依赖参数化查询或ORM(如SQLAlchemy);禁用字符串拼接SQL,表名/字段名须白名单校验,勿信黑名单过滤。

Flask本身不处理SQL注入,得靠数据库层和写法规避
Flask只是一个Web框架,它不解析SQL、不校验查询语句,更不会自动拦截SELECT * FROM users WHERE id = '1 OR 1=1'这类恶意输入。所谓“拦截SQL注入”,实际是避免把用户输入拼进SQL字符串里——只要不用str.format()或%拼接SQL,基本就绕开了最常见漏洞。
用ORM(如SQLAlchemy)或参数化查询才是正解
SQLAlchemy默认使用参数化查询,所有用户数据都经DBAPI(如psycopg2或pymysql)安全绑定,底层会把user_input当纯数据而非SQL片段处理:
# ✅ 安全:参数化查询(原生SQL)
cursor.execute("SELECT * FROM users WHERE name = %s", (request.args.get('name'),))
<h1>✅ 安全:SQLAlchemy ORM</h1><p>User.query.filter(User.name == request.args.get('name')).first()</p><h1>❌ 危险:字符串拼接(绝对不要这么写)</h1><p>name = request.args.get('name')
cursor.execute(f"SELECT * FROM users WHERE name = '{name}'") # 可被闭合引号绕过
注意:request.args.get()返回的值始终是字符串,即使看起来像数字,也必须走参数占位符,不能转int()后直接拼接。
立即学习“Python免费学习笔记(深入)”;
别信“过滤函数”或正则黑名单
试图用re.sub(r"(union|select|;|--|#)", "", input)这类逻辑防SQL注入,既漏报又误杀,还给攻击者提供试探反馈。真实攻击可能用宽字节、注释符变体、大小写混用(SeLeCt)、URL编码绕过,维护黑名单成本远高于坚持参数化。
如果非得做输入预处理(比如限制字段长度、白名单枚举值),只应在业务逻辑层做,且与SQL构造完全解耦:
- 允许的
sort_by字段限定为['id', 'created_at', 'name'],不在列表内直接abort(400) -
limit参数强制转int并限制范围(如min(1, max(100, int(val)))) - 永远不把
request.form或request.json的任意键名当作表名/列名拼进SQL
警惕ORM里的“原生表达式”陷阱
SQLAlchemy的text()、func.concat()、Query.from_self()等高级用法,一旦混入未过滤的用户输入,照样触发注入:
# ❌ 危险:text()中直接插值
from sqlalchemy import text
db.session.execute(text(f"SELECT * FROM {table_name}")) # table_name来自request!
<h1>✅ 安全:表名/列名必须白名单校验后再用</h1><p>allowed_tables = {'users', 'orders'}
if table_name not in allowed_tables:
abort(400)
db.session.execute(text(f"SELECT * FROM {table_name}"))
真正难防的从来不是' OR 1=1 --,而是开发者自己用getattr(model, request.args.get('field'))动态取字段、再喂给order_by()——这种反射调用若没校验字段名白名单,参数化也救不了。


















