Spring Boot Actuator 被打穿:线上开了这些端点,等于裸奔
前段时间 CVE-2026-22733 暴出 Spring Boot 认证绕过漏洞,我们紧急排查了所有项目的 Actuator 配置。结果发现:一半以上的项目 Actuator 端点全开,没有任何鉴权。
一、事故现场
安全团队发来一封邮件:
紧急通知:检测到多个线上服务暴露了 Spring Boot Actuator 端点,/env、/heapdump、/shutdown 均可未授权访问。要求 24 小时内修复。
我一看,果然。我们的一个微服务,Actuator 配置长这样:
yaml
management:
endpoints:
web:
exposure:
include: "*" # 所有端点全部暴露
endpoint:
shutdown:
enabled: true # 甚至开了远程关机
这意味着什么?任何人访问 http://你的域名/actuator/env 就能看到所有环境变量(包括数据库密码、Redis 密码、第三方 API Key)。访问 /actuator/heapdump 可以下载整个堆内存 dump,里面什么都有。访问 /actuator/shutdown 可以直接把服务关掉。
不是夸张,线上服务等于裸奔。
二、Actuator 到底暴露了什么
Spring Boot Actuator 是生产监控组件,提供一系列 HTTP 端点查看应用状态。问题在于很多人为了"方便调试"把所有端点都开了,却没加鉴权。
2.1 高危端点清单
| 端点 | 功能 | 危险等级 | 泄露什么 |
|---|---|---|---|
/actuator/env |
查看所有环境变量 | 极高 | 数据库密码、Redis 密码、API Key |
/actuator/heapdump |
下载堆内存 dump | 极高 | 堆里的所有对象(含密码、token、用户数据) |
/actuator/shutdown |
关闭应用 | 极高 | 直接让服务下线 |
/actuator/threaddump |
线程转储 | 高 | 线程栈信息,可分析业务逻辑 |
/actuator/configprops |
查看配置属性 | 高 | 数据源配置、连接池配置 |
/actuator/mappings |
查看所有 URL 映射 | 中 | 暴露所有接口路径 |
/actuator/beans |
查看所有 Spring Bean | 中 | 暴露应用结构 |
/actuator/loggers |
查看和修改日志级别 | 中 | 可动态调高日志级别导致磁盘写满 |
/actuator/health |
健康检查 | 低 | 暴露数据库/Redis 连通性 |
2.2 CVE-2026-22733 的关键点
这个漏洞的核心是:当应用将需要认证的业务端点声明在 CloudFoundry Actuator 路径下(如 /cloudfoundryapplication/admin)时,攻击者可以通过该路径绕过 Spring Security 的认证。
简单说,Spring Security 对 Actuator 端点和普通业务端点的安全处理方式不同。如果你的业务接口恰好映射到了 Actuator 的路径下,它可能被当作 Actuator 端点处理,跳过了你配置的认证逻辑。
受影响版本:Spring Boot 2.7.0-2.7.31、3.3.0-3.3.17、3.4.0-3.4.14、3.5.0-3.5.11。修复版本:2.7.32、3.3.18、3.4.15、3.5.12。如果你的项目在这些范围内,尽快升级。
三、5 秒复现:你的服务裸奔了吗
3.1 检查你的配置
yaml
# application.yml - 危险配置
management:
endpoints:
web:
exposure:
include: "*" # ❌ 所有端点暴露
endpoint:
shutdown:
enabled: true # ❌ 远程关机
yaml
# application.yml - 安全配置
management:
endpoints:
web:
exposure:
include: health,info,metrics # ✅ 只开放必要端点
base-path: /manage # ✅ 改掉默认路径
endpoint:
shutdown:
enabled: false # ✅ 关闭远程关机
server:
port: 9090 # ✅ 独立端口,不跟业务端口混在一起
3.2 验证你的服务
直接在浏览器访问:
bash
http://localhost:8080/actuator/env
http://localhost:8080/actuator/heapdump
http://localhost:8080/actuator/shutdown
- 如果返回 JSON 数据(包含环境变量)→ 裸奔了,立刻修
- 如果返回 404 → 端点没暴露,基本安全
- 如果返回 401 → 有鉴权,问题不大
四、怎么修:3 层防护
第 1 层:最小化端点暴露(必须做)
yaml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
exclude: env,heapdump,threaddump,beans,mappings,configprops
endpoint:
shutdown:
enabled: false
health:
show-details: when-authorized # 健康详情只给授权用户看
只开放运维必需的端点:health(健康检查)、info(应用信息)、metrics(指标)、prometheus(监控采集)。其余全部关闭。
注意
health.show-details:默认配置下/actuator/health会暴露数据库、Redis 的连通性详情。设成when-authorized让未授权用户只能看到{"status":"UP"},看不到细节。
第 2 层:独立管理端口(强烈建议)
yaml
management:
server:
port: 9090 # Actuator 端口跟业务端口分开
address: 127.0.0.1 # 只允许本机访问(或内网 IP)
Actuator 跑在 9090 端口,业务跑在 8080。外部流量通过 Nginx 只转发 8080,9090 不对外暴露。监控系统从内网直接访问 9090 采集数据。
这是最有效的隔离方式:即使 Actuator 端点全开,外部也访问不到。
第 3 层:加鉴权(兜底)
java
@Configuration
public class ActuatorSecurityConfig {
@Bean
SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll() // 健康检查放行
.anyRequest().hasRole("ADMIN") // 其余需要 ADMIN 角色
)
.httpBasic(Customizer.withDefaults()); // Basic 认证
return http.build();
}
}
yaml
spring:
security:
user:
name: monitor
password: ${MONITOR_PASSWORD} # 密码从环境变量读,别硬编码
roles: ADMIN
即使前两层都失效,还有鉴权兜底。健康检查放行(K8s 探针需要),其余端点需要 ADMIN 权限。
五、heapdump 泄露了怎么办
如果之前线上裸奔过,/actuator/heapdump 可能已经被人下载了。堆内存里有什么?
- 数据库连接字符串和密码
- Redis 密码
- JWT token / Session
- 用户手机号、身份证号等业务数据
- 第三方 API Key(支付、短信、OSS)
应急处理:
- 立刻改密码:数据库、Redis、所有第三方 API Key 全部轮换
- 检查访问日志 :看有没有异常 IP 访问过
/actuator/heapdump和/actuator/env - 检查依赖:确认 Spring Boot 版本不在 CVE-2026-22733 影响范围内(2.7.0-2.7.31、3.3.0-3.3.17、3.4.0-3.4.14、3.5.0-3.5.11),如果在就升级到对应修复版本
- 关闭端点:按上面的三层防护修复
六、CheckList:Actuator 安全排查
| # | 检查项 | 风险点 | 正确做法 |
|---|---|---|---|
| 1 | include: "*" | 所有端点暴露 | 只开放 health,info,metrics,prometheus |
| 2 | shutdown.enabled: true | 远程关机 | 设为 false |
| 3 | 没有独立端口 | Actuator 跟业务混在一起 | management.server.port 独立端口 |
| 4 | 管理端口对外暴露 | 任何人可访问 | 只绑定内网 IP 或 Nginx 不转发 |
| 5 | 没有鉴权 | 端点无保护 | Spring Security 保护 + Basic 认证 |
| 6 | health.show-details: always | 暴露 DB/Redis 连通性 | 设为 when-authorized |
| 7 | Spring Boot 版本在 CVE 影响范围 | 认证绕过漏洞 | 升级到安全版本 |
| 8 | 之前裸奔过 | 密码可能已泄露 | 立即轮换所有密码和 API Key |
七、总结
Actuator 是好东西,但全开等于给黑客送了一份应用说明书。环境变量、堆内存、线程栈、所有接口路径全都能看。
三层防护:
- 最小化暴露:只开 health,info,metrics,prometheus,关闭 shutdown
- 独立端口:management.server.port 跟业务端口分开,不对外暴露
- 加鉴权:Spring Security 保护,health 放行其余需要 ADMIN
如果之前裸奔过,别犹豫,立刻改密码,立刻关端点,立刻查日志。
附录:安全配置模板
yaml
# application.yml - Actuator 安全配置模板
management:
server:
port: 9090 # 独立管理端口
address: 127.0.0.1 # 只允许本机访问(生产环境改内网 IP)
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
exclude: env,heapdump,threaddump,beans,mappings,configprops,loggers
endpoint:
shutdown:
enabled: false # 关闭远程关机
health:
show-details: when-authorized # 健康详情只给授权用户
show-components: never # 不暴露组件详情
info:
env:
enabled: false # 不暴露环境变量
java:
enabled: true # 只暴露 Java 版本信息
spring:
security:
user:
name: ${MONITOR_USER:monitor}
password: ${MONITOR_PASSWORD} # 密码从环境变量读
roles: ADMIN
直接复制这套配置到 application.yml,配合 Spring Security 依赖即可使用。 生产环境把
address改成内网 IP,监控系统从内网访问 9090 端口采集数据。