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

直接搜 SELECT、INSERT、UPDATE、DELETE 这类关键字
SQL注入的起点几乎总在拼接语句的地方,而拼接往往发生在显式写死的 SQL 字符串里。不靠猜测,直接用 IDE 或命令行全局搜索这些动词(大小写不敏感)最有效。
常见错误现象:只搜 mysql_query 或 mysqli->query,结果漏掉大量用 PDO::exec、executeUpdate(Java)、db.query(Python ORM 封装)等间接调用的点。
- 优先搜 SQL 关键字本身,而非执行函数——因为拼接逻辑可能在上层封装里,执行函数只是“最后一跳”
- 配合正则:
(select|insert|update|delete|union)\s+from,能过滤掉注释或变量名干扰 - Java 项目额外注意 MyBatis 的
<script></script>标签和${}占位符——它们不走预编译,等同于字符串拼接
重点盯住 +、.、format、%、concat 这些拼接操作
拼接符号比 SQL 动词更隐蔽,也更危险。一旦发现用户输入变量出现在这些操作符附近,基本可判定为高危点。
使用场景:PHP 中 "SELECT * FROM user WHERE id = " . $_GET['id'];Java 中 "SELECT * FROM user WHERE name = '" + username + "'";Python 中 f"WHERE id = {user_id}"。
-
+(Java/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"];Java 项目里 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 里——这些地方人眼容易跳过,必须结合数据流从 sink 往 source 追。











