3. 注入风险分类与攻击面
注入类漏洞的共同本质,是用户可控数据未经恰当处理就进入了某个“解释器”,被解释器当作代码、查询或指令的一部分执行。不同注入类型的差异,主要来自三件事:解释器是谁(SQL 引擎、文档数据库、操作系统 Shell、目录服务、XML 解析器、模板引擎、表达式求值器)、数据从哪里进入(URL 参数、表单、Header、Cookie、JSON 体、文件名、日志字段),以及拼接发生在哪一层(应用代码、ORM、模板、配置)。理解这三要素,就能把纷繁的注入类型归入同一张攻击面地图。
下面这张图按“解释器类型—典型入口—触发条件—影响范围”梳理七类注入,可作为排查与设计防护时的对照参考。
SQL 注入:最经典,也最容易被低估
SQL 注入的触发条件非常明确:用户输入被拼进 SQL 语句的“结构位置”,而不是作为纯数据传入。典型场景包括登录查询、搜索过滤、排序字段、分页参数、IN 列表。例如后端写成 "SELECT * FROM users WHERE name='" + name + "'",当 name 传入 ' OR '1'='1 时,条件恒真,登录被绕过。更危险的是堆叠查询与联合查询,可进一步读取其他表、写入文件甚至调用数据库扩展。
防护上,参数化查询(预编译)是根本手段,它让 SQL 结构与数据在协议层分离;表名、列名、排序方向等无法参数化的位置,必须用白名单枚举映射,而不是转义。数据库账户应遵循最小权限,Web 应用账户不应具备 DROP、FILE 等权限。
NoSQL 注入:对象与操作符的陷阱
以 MongoDB 为例,若后端直接把请求体对象传入查询,如 db.users.find({username: req.body.username, password: req.body.password}),攻击者提交 {"username":"admin","password":{"$ne":null}},查询就变成“密码不等于 null”,从而绕过认证。触发条件是把用户输入当作查询对象或操作符,而非字符串值。防护要点是强制类型校验(密码必须是字符串)、拒绝对象型输入、使用 $eq 显式匹配,并禁用服务端 $where 等脚本求值。
命令注入:从参数到 Shell 的一步之遥
当应用调用 system()、exec()、Runtime.exec() 并拼接用户输入时,;、|、&&、反引号、$() 都可能截断原命令并追加新命令。例如图片处理接口拼接文件名 convert user.jpg out.png,若文件名传入 a.jpg; cat /etc/passwd,就会执行额外命令。防护上应避免调用 Shell,改用参数数组形式执行;必须调用时,对输入做严格白名单,并让进程以低权限账户运行。
LDAP 与 XPath 注入:过滤器与路径表达式的拼接
LDAP 注入发生在目录服务查询过滤器拼接时,如 (&(uid=" + user + ")(password=" + pwd + ")),输入 *)(uid=*))(|(uid=* 可改变过滤逻辑,绕过认证或枚举用户。XPath 注入类似,输入 ' or '1'='1 可让 XML 节点查询恒真。两者防护思路一致:使用参数化 API 或对特殊字符 * ( ) \ NUL 做转义,并对查询结果做权限校验。
模板注入与表达式注入:当输入被当作代码求值
模板注入(SSTI)的触发条件是用户输入被拼接进模板内容并被引擎编译,例如 render_template_string("Hello " + name),输入 {{7*7}} 会返回 49,说明表达式被执行;进一步可利用引擎特性读取配置、执行命令。表达式注入(SpEL、OGNL、MVEL)同理,当框架对用户输入调用 parseExpression 或 getValue 时,攻击者可构造 T(java.lang.Runtime).getRuntime().exec(...) 实现 RCE。防护核心是不把用户输入当模板或表达式,模板变量只传数据;必须动态求值时,使用沙箱、白名单函数与最小上下文对象。
攻击面收敛的检查清单
| 检查项 | 关注点 | 判断依据 |
|---|---|---|
| 查询构造 | 是否存在字符串拼接 SQL / NoSQL 对象 | 代码中出现 + 拼接查询或直接传对象 |
| 系统调用 | 是否调用 Shell 且拼接输入 | 出现 exec、system、Runtime.exec |
| 目录/XML 查询 | 过滤器与 XPath 是否拼接 | 出现 uid=、//user[ 等拼接 |
| 模板与表达式 | 用户输入是否进入模板编译或求值 | 出现 render_template_string、parseExpression |
| 权限与日志 | 账户权限是否最小、异常是否记录 | 数据库账户权限、查询日志告警 |