课程笔记:XML注入、代码注入、OS命令注入攻击
课程名称:计算机网络应用 核心摘要:本讲延续 SQL 注入主题,系统讲解三种注入攻击:XML 注入(用户数据被当作 XML 节点解析)、代码注入(Code Injection,主要为 JS 脚本注入)、OS 命令注入(OS Command Injection,将输入作为操作系统命令执行)。重点剖析三类攻击的成因、案例、危害及防护方案,强调"数据与代码分离"原则。
一、 核心概念与原理
1.1 注入攻击的共性原理
所有注入攻击都违背了一个根本原则——数据与代码分离:
- 程序把用户输入的数据当作代码/节点/命令去执行或解析
- 未对输入做转义、校验或隔离,导致恶意构造的数据改变程序原有语义
1.2 注入攻击两大成立条件
| 序号 | 条件 | 说明 |
|---|---|---|
| 1 | 用户能控制数据的录入 | 如通过 request.getParameter() 获取用户输入 |
| 2 | 程序直接拼接数据 | 未做任何转义或校验,直接拼入可执行上下文 |
1.3 三类注入攻击对比
| 对比维度 | SQL 注入 | XML 注入 | 代码注入 | OS 命令注入 |
|---|---|---|---|---|
| 注入载体 | SQL 语句 | XML 节点 | JS/脚本代码 | 操作系统命令 |
| 执行环境 | 数据库引擎 | XML 解析器 | 脚本引擎(如 JS 引擎) | 操作系统 Shell |
| 出现频率 | 高 | 较低(微服务时代 XML 存储减少) | 较低(Java Web 中少见) | 较低(系统很少对外开放) |
| 危害程度 | 高 | 中 | 极高 | 极高 |
二、 技术细节与协议分析
2.1 XML 注入(XML Injection)
定义:将用户录入的信息作为 XML 节点 解析执行,而非普通文本数据。
发生场景:对 XML 数据做查询或修改(增、删、改均属修改)时,输入或输出的参考数据均可能引发漏洞。
攻击案例剖析
服务端期望用户录入两个参数(name、email),拼接为 XML:
<!-- 正常输入 -->
<user>
<name>郭德纲</name>
<email>guodegang@deyunshe.com</email>
</user>
恶意用户在第二个参数中注入额外标签,闭合原标签并新增节点:
<!-- 恶意输入(email 参数) -->
user1@lagou.com</email>
</user>
<user>
<name>user2</name>
<email>user2@lagou.com
结果:原本应录入 1 条数据,实际被解析为 2 条 user 记录,完成 XML 注入。
防护方案
保存或展示前对数据做转义,使用工具类对特殊字符编码:
// 使用 Apache Commons 工具类进行 XML 编码转义
String safeName = StringEscapeUtils.escapeXml(request.getParameter("name"));
String safeEmail = StringEscapeUtils.escapeXml(request.getParameter("email"));
转义后,用户输入的 <、> 等标签符号变为普通文本,不再被解析为 XML 节点。
2.2 代码注入(Code Injection)
定义:允许用户输入代码片段并在服务器端执行,未做判断与控制,导致恶意代码运行。
Java Web 中少见的原因:
- Java 代码需经编译(
.java→.class)才能由 JVM 运行,无法直接注入执行 - 实际威胁多为 JS 脚本注入(浏览器内置 JS 引擎可直接解释执行)
- 故"代码注入"更准确的称呼是 脚本注入
攻击案例剖析
通过 Java 脚本引擎 API 执行用户输入的 JS 代码:
// 1. 初始化脚本引擎管理器
ScriptEngineManager manager = new ScriptEngineManager();
// 2. 获取 JavaScript 脚本引擎
ScriptEngine engine = manager.getEngineByName("JavaScript");
// 3. 执行用户输入(危险!未做校验)
engine.eval(request.getParameter("code"));
正常输入:print("hello");
恶意输入(导入 Java 文件包并在磁盘创建文件):
// 前面正常打印,后面导入 Java IO 包创建文件
print("hello");
importPackage(java.io);
var f = new File("attack.txt");
f.createNewFile();
// 进一步可通过流扫描磁盘、修改数据文件
危害:恶意用户可远程控制服务器,获取服务器权限,篡改资源,甚至控制数据库。
防护方案
| 防护策略 | 具体做法 |
|---|---|
| 禁用危险函数 | 禁止 eval 等执行命令的函数 |
| 输入限制 | 执行代码的参数、文件名禁止与用户输入相关 |
| 索引化输入 | 仅允许用户输入 1/2/3 等索引号,由程序映射到具体操作 |
| 白名单机制 | 限制可用函数集合,仅允许安全函数 |
根本原则:代码注入由不安全的编程习惯引起,危险函数应避免在开发中使用;若非必须,不应让用户输入代码。
2.3 OS 命令注入(OS Command Injection)
定义:注入的有效载荷(payload)被作为操作系统命令执行。OS = Operating System(操作系统)。
主流服务器系统:
| 技术栈 | 部署系统 |
|---|---|
| ASP.NET / C#(微软技术栈) | Windows Server |
| PHP / Java 开发 | Linux |
常用系统命令复习
| 功能 | Linux | Windows |
|---|---|---|
| 查看当前用户 | whoami | whoami |
| 查看系统信息 | uname -a | — |
| 网络配置 | ifconfig | ipconfig |
| 查看网络连接 | netstat -an | netstat -an |
| 查看进程 | ps -ef | — |
攻击案例剖析
功能场景:验证服务器到目标 IP 的网络状况(ping 命令)。
服务端代码(未校验):
// 执行 shell 脚本,拼接用户输入的 IP
String ip = request.getParameter("ip");
Runtime.getRuntime().exec("ping " + ip);
正常输入:127.0.0.1
恶意输入(利用命令连接符追加执行其他命令):
# 输入内容:ping 127.0.0.1 && whoami
127.0.0.1 && whoami
结果:服务端不仅执行 ping,还执行了 whoami(查看当前用户)。进一步可执行 ps -ef(查看进程)、kill(杀死进程)等任意命令,后果极其严重。
注:DVWA 靶机平台提供了 Command Injection 模块用于演练该漏洞。
防护方案
| 优先级 | 防护策略 | 说明 |
|---|---|---|
| 最优 | 不调用 OS 命令 | 永远不要从应用代码中调用操作系统命令 |
| 次优 | 使用安全 API | 几乎每种场景都有更安全的平台 API 替代 |
| 兜底 | 白名单校验 | 仅允许输入特定 IP 地址白名单 |
| 兜底 | 正则校验 | 验证输入是否为合法 IP 格式 |
| 兜底 | 字符过滤 | 仅允许字母数字,禁止 &&、` |
三、 实践应用与配置命令
3.1 XML 注入防护命令
// Apache Commons Lang XML 转义
import org.apache.commons.text.StringEscapeUtils;
String safeInput = StringEscapeUtils.escapeXml11(
request.getParameter("userData")
);
// 转义规则:< → < > → > & → & " → " ' → '
3.2 OS 命令注入校验示例
// 正则校验:仅允许合法 IP 格式,排除命令连接符
String ip = request.getParameter("ip");
String ipRegex = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$";
if (ip != null && ip.matches(ipRegex)) {
// 校验通过,可执行(仍建议优先用安全 API 替代 ping)
Process p = Runtime.getRuntime().exec("ping " + ip);
} else {
// 拒绝非法输入
throw new IllegalArgumentException("非法 IP 地址");
}
3.3 DVWA 靶机演练
- 模块:Command Injection
- 输入框:请输入 IP 地址
- 正常提交:
127.0.0.1→ 返回 ping 结果 - 注入提交:
127.0.0.1 && whoami→ 返回 ping 结果 + 当前用户
四、 重点与难点提示
- 核心原则:所有注入攻击的本质都是违背数据与代码分离——把用户数据当代码执行。
- 易错点:XML 注入不是注入 SQL,而是注入 XML 节点;区别于 SQL 注入(注入 SQL 语句)。
- 易错点:Java Web 中代码注入多为 JS 脚本注入而非 Java 代码注入(Java 需编译,JS 由引擎直接解释)。
- 考点:注入攻击成立的两大条件——①用户可控输入;②程序直接拼接未校验。
- 考点:OS 命令注入的命令连接符
&&(逻辑与)、||(逻辑或)、;、|等均可用于追加恶意命令。 - 防护要点:OS 命令注入最有效的防护是"不调用 OS 命令",用安全 API 替代;其次白名单 + 正则校验。
- 面试题:简述 XML 注入、代码注入、OS 命令注入的原理及防护方案。
- 面试题:为什么 Java Web 应用中代码注入较少见?(Java 需编译,JS 才可由浏览器/引擎直接执行)
五、 课后疑问/遗留问题
- 微服务架构下 XML 存储被 JSON 等替代,XML 注入是否仍有现实威胁?哪些遗留系统需重点排查?
- 代码注入中
ScriptEngine执行 JS 的场景,是否存在沙箱(Sandbox)隔离方案? - OS 命令注入中,Windows 与 Linux 的命令连接符差异有哪些?如何完整枚举过滤?
ProcessBuilder相比Runtime.exec在安全性上有何优势?后续课程是否会讲解?- 后续课程是否会讲解 反序列化漏洞、LDAP 注入、XPath 注入、日志注入 等其他注入形式?