SQL注入起点总在SQL关键字拼接处,应全局搜索SELECT/INSERT/UPDATE/DELETE等动词及+、.、format等拼接操作,重点关注用户输入是否经预编译处理,警惕宽字节绕过与二次注入。

直接搜 SELECT、INSERT、UPDATE、DELETE 这类关键字
说到底,SQL注入的根源几乎都出在字符串拼接上。而拼接最常发生在哪里?就在那些显式写死的SQL语句里。所以,别靠感觉去猜,最直接有效的方法,就是用IDE或者命令行工具,对整个项目进行全局搜索,目标就是这几个核心的SQL动词——记得要大小写不敏感。
新手常犯的一个错误是,只盯着mysql_query或者mysqli->query这类具体的执行函数去搜。结果呢?大量使用PDO::exec、Ja va里的executeUpdate,甚至是Python ORM封装后的db.query调用点,就这么被漏掉了。
- 核心思路是搜SQL关键字本身,而不是执行函数。 因为拼接的逻辑可能隐藏在上层的封装里,执行函数只是最后一步的“搬运工”。
- 可以配合正则表达式来提升效率,比如
(select|insert|update|delete|union)\s+from,这样能有效过滤掉代码注释或者变量名带来的干扰。 - 对于Ja va项目要额外留心,比如MyBatis框架中的
标签和${}占位符——它们本质上就是字符串拼接,并不会走预编译流程。
重点盯住 +、.、format、%、concat 这些拼接操作
相比SQL动词,这些拼接符号往往更隐蔽,但也更危险。一旦发现用户输入的变量出现在这些操作符旁边,基本就可以判定为高危风险点了。
这样的场景随处可见:PHP里"SELECT * FROM user WHERE id = " . $_GET['id'];Ja va里"SELECT * FROM user WHERE name = '" + username + "'";Python里f"WHERE id = {user_id}"。
- 记住,
+(在Ja va/C#里)、.(在PHP里)、%和.format()(在Python里),这些都意味着字符串在运行时进行了拼接,从根本上就无法阻止注入。 - 要特别警惕那些“看起来”安全的写法,比如
String.format("...%s...", input)或者MessageFormat.format(...)——它们本质上依然是拼接,安全假象而已。 - Node.js里也一样,
query(`SELECT * FROM x WHERE y = ${input}`)这种使用模板字符串的写法,同样存在风险。
检查变量来源是否可控,别轻信 $_POST 以外的入口
很多人在审计时,眼睛只盯着$_GET和$_POST。殊不知,$_COOKIE、$_SERVER['HTTP_REFERER']、$_REQUEST,甚至是读取的文件内容、从数据库里取出来的值,都可能成为污染源。
现实中的案例差异很大:比如ZZCMS的漏洞点就在$_COOKIE["askbigclassid"];而在Ja va项目里,request.getHeader("X-Forwarded-For")被直接拼进SQL语句的情况也屡见不鲜。
- 因此,有必要全局搜索
$_COOKIE、getHeader(、getRemoteAddr()、file_get_contents(等函数,然后顺着数据流去看它们最终是否流入了SQL语句。 - 更要警惕“二次注入”:数据第一次存入数据库时可能经过了过滤(看似安全了),但当它被再次导出、导入或用于其他查询时,原样的恶意数据就被执行了——像
/admin/data.php这类数据管理功能,特别容易中招。 - 千万别假设“后台接口外人访问不到”。
admin/目录下那些缺乏鉴权的API或者遗留的调试接口,往往是攻击者最喜欢的突破口。
绕过过滤的典型模式:看是否用 addslashes、mysql_real_escape_string 或 magic_quotes
这里有个关键认知:加了“过滤”不等于就安全了。很多老系统还在使用早已过时、且存在明确绕过方案的防御手段,尤其是在字符集设置不当或存在宽字节问题时,这些过滤形同虚设。
从性能和兼容性角度看,MySQL 5.7以上版本默认关闭了magic_quotes_gpc,但如果代码里为了兼容旧版还保留着相关逻辑,反而会给人一种虚假的安全感。
addslashes()在面对MySQL的宽字节编码(比如GBK)时是无效的,经典的%df%27就能轻松绕过。mysql_real_escape_string()这个函数本身已被弃用,而且它的有效性依赖于当前数据库连接的字符集设置,并不靠谱。- 如果在代码里看到
if (get_magic_quotes_gpc()) { ... }这样的判断,就应该立刻警觉——这是十几年前的防御方式了,放在今天,基本等于没有设防。
话说回来,在实际的代码审计工作中,最棘手的往往不是找不到拼接点,而是拼接发生在多层封装之后,或者混杂在日志埋点、缓存键生成、权限校验的SQL片段里。这些地方人眼很容易跳过,必须结合数据流分析,从最终执行SQL的“汇点”反向追踪到用户输入的“源头”,才能一网打尽。
