sql注入测试应从拼接用户输入的select语句where子句开始,重点检查request.query/form参数直拼场景,优先审计str.format()、+、%等字符串拼接及statement.execute()等危险调用。

SQL注入测试该从哪条语句开始打点
真实开发中,SELECT 语句最容易被绕过校验——尤其带 WHERE 子句且参数来自 request.query 或 request.form 的场景。别一上来就扫全库,先盯住所有拼接了用户输入的 WHERE 条件,比如 WHERE username = '{user_input}' 这类硬拼字符串的写法。
- 检查所有使用
str.format()、%或+拼接 SQL 的 Python 文件(尤其是 Flask/Django 的视图层) - Node.js 里重点看
mysql.query(sql, params)是否把参数直接塞进sql字符串里,而不是传给第二个参数 - Java 的
Statement.execute()比PreparedStatement.execute()危险得多,搜new Statement比搜execute更有效
为什么预编译参数不能只靠框架自动处理
Django 的 ORM、Rails 的 ActiveRecord 确实默认防注入,但一旦你调用 raw()、extra()、find_by_sql() 或执行 cursor.execute(sql, params) 时手动拼 sql 字符串,就等于主动退出安全区。
-
cursor.execute("SELECT <em> FROM users WHERE id = %s", [user_id])</em>安全;但cursor.execute("SELECT FROM users WHERE id = " + str(user_id))不安全 - PostgreSQL 的
jsonb_path_query()、MySQL 的PREPARE/EXECUTE动态语句,参数无法绑定,必须额外做白名单校验或正则过滤 - ORM 的
order_by()和annotate()如果接收用户传入字段名(如request.GET.get('sort')),字段名本身不能参数化,得用白名单比对:if sort_field not in ['created_at', 'score']:
集成测试里怎么模拟真实注入载荷
CI 流水线里跑的不是教科书式 ' OR 1=1 --,而是要覆盖真实 WAF/数据库行为差异。比如 MySQL 5.7 默认关闭 sql_mode=STRICT_TRANS_TABLES,UNION SELECT 可能静默失败;而 PostgreSQL 对类型强制更敏感,CAST('1' AS INT) 和 CAST('1' AS TEXT) 行为不同。
- 在测试用例里加几组“半成功”载荷:
'::int--(PostgreSQL 类型转换绕过)、1; DROP TABLE users--(多语句执行,需确认数据库连接是否启用allowMultiQueries=true) - 用
sqlmap -r request.txt --batch --level=3导出的载荷不如自己写小脚本发请求:HTTP 层可能拦截UNION关键字,但放 base64 后再解码就过了,所以测试得走真实路由,别只测 DAO 层 - 所有测试必须验证响应体是否含敏感数据(如
email、password_hash字段),不能只看 HTTP 状态码是否为 200
上线后如何低成本捕获漏网的拼接点
日志里搜 SELECT.<em>WHERE.</em>+.<em></em>、query.".<em>{.</em>} 这类正则只能发现明面上的拼接。更有效的办法是,在数据库驱动层加轻量钩子:比如 Python 的 pymysql 可 patch Connection.query(),记录所有含单引号且含用户输入变量名(如 user_id、search_term)的原始 SQL;Node.js 的 mysql2 可监听 connection.on('query', sql => {...})。
- 钩子不拦截请求,只记录可疑 SQL 和调用栈,每天聚合一次,人工抽检前 20 条
- 注意排除 ORM 自动生成的迁移语句、健康检查 SQL(比如含
SELECT 1的) - 如果用了连接池,钩子得注册在每次
getConnection()返回的实例上,而不是初始化时的 pool 对象上,否则会漏掉复用连接的请求
真正难防的从来不是 ' OR 1=1 --,而是那些藏在 JSON 字段解析后、再拼进 SQL 的值,或者前端传来的排序字段名被直接塞进 ORDER BY——这种地方既不会报错,也不会进常规扫描范围。










