背景
Spring Boot Actuator 是很多 Java Web 项目都会启用的运维组件,用来暴露健康检查、指标、环境信息、线程状态等管理端点。它本身不是漏洞,但在真实项目里,经常因为默认认知偏差、网关转发不清晰、历史配置遗留,导致管理端点暴露到公网或被内部低权限用户访问。
这类问题在代码审计、攻防演练和应急排查中都比较常见。风险不一定表现为直接拿到服务器权限,更多时候是信息泄露、配置泄露、服务拓扑泄露,进一步放大其他漏洞的利用条件。本文按审计和加固视角整理一套相对稳妥的检查方法。
常见问题场景
实际项目里,Actuator 暴露风险通常来自下面几类场景:
- 开发阶段为了调试启用了
management.endpoints.web.exposure.include=*,上线后未收敛。 - 服务部署在内网,但通过网关、Ingress、反向代理被间接转发到公网。
- 健康检查路径和管理端点共用同一端口,网关规则写得过宽。
- Spring Security 只保护了业务路径,没有覆盖
/actuator/**。 - 旧版本项目存在历史端点,例如
/env、/trace、/heapdump等暴露面较大。
从风险角度看,比较敏感的端点包括 env、configprops、beans、mappings、threaddump、heapdump、logfile、prometheus。其中 health 和 info 通常风险较低,但也需要注意不要输出过多内部细节。
技术分析
Actuator 的访问面由几个因素共同决定:依赖是否引入、端点是否启用、Web 暴露范围、监听端口、认证授权策略、网关转发策略。只看某一个配置项容易漏判。
典型依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>在 Spring Boot 2.x/3.x 中,Actuator 端点默认只暴露少量 Web 端点,常见是 health、info。但如果项目中出现如下配置,暴露面会明显扩大:
management.endpoints.web.exposure.include=*或者 YAML 形式:
management:
endpoints:
web:
exposure:
include: "*"需要注意,enabled 和 exposure 是两个不同维度。端点启用不代表一定通过 Web 暴露,通过 Web 暴露也不代表具备安全访问控制。审计时建议同时检查:
management.endpoint.<name>.enabledmanagement.endpoints.enabled-by-defaultmanagement.endpoints.web.exposure.includemanagement.endpoints.web.exposure.excludemanagement.server.portmanagement.server.addressmanagement.endpoints.web.base-path
审计关键步骤
下面是一套偏代码审计和配置核查的流程,适合在企业内部自查、项目上线前检查、攻防演练前资产梳理时使用。
1. 检查依赖和版本
首先确认项目是否引入 Actuator,以及 Spring Boot 版本。Maven 项目可以查看 pom.xml,Gradle 项目可以查看 build.gradle。也可以在构建环境中执行:
mvn dependency:tree | grep actuator./gradlew dependencies | grep actuator版本检查的目的不是单纯追 CVE,而是判断默认行为。例如 Spring Boot 1.x 与 2.x 之后端点路径、默认暴露策略都有差异。老项目迁移时尤其容易出现安全策略误判。
2. 搜索管理端点配置
建议在代码仓库内搜索以下关键词:
management.endpoints
management.endpoint
management.server
endpoints.enabled
actuator
heapdump
threaddump
prometheus重点关注不同环境配置文件,例如:
application.ymlapplication-prod.ymlapplication-test.ymlbootstrap.yml- 配置中心中的线上配置
- Kubernetes ConfigMap / Secret
很多问题不是出在仓库默认配置,而是出在线上配置中心覆盖。审计时如果只看代码仓库,很容易漏掉真实风险。
3. 判断暴露范围是否过宽
不建议在生产环境使用 include=*。如果确实需要监控指标,应尽量使用白名单策略,例如:
management:
endpoints:
web:
exposure:
include: health,info,prometheus
base-path: /actuator对于不需要的敏感端点,可以显式排除:
management:
endpoints:
web:
exposure:
exclude: env,beans,configprops,heapdump,threaddump,logfile,mappings这里要注意,exclude 优先级通常高于 include,但不同版本和组合配置下仍建议做实际验证,不要只依赖预期。
4. 检查管理端口和监听地址
比较推荐的方式是将管理端口与业务端口分离,并限制监听地址或网络访问范围。例如:
server:
port: 8080
management:
server:
port: 9001
address: 127.0.0.1如果部署在容器或 Kubernetes 中,127.0.0.1 的含义要结合运行环境确认。容器内监听本地地址不等于宿主机或集群外部可访问,但 Sidecar、端口映射、Service 配置都可能改变实际暴露面。
Kubernetes 环境还需要检查:
- Service 是否暴露了 management port。
- Ingress 是否存在
/actuator路径转发。 - Prometheus 抓取配置是否使用了过宽的 ServiceMonitor。
- NetworkPolicy 是否限制了访问来源。
5. 检查 Spring Security 覆盖范围
很多项目只写了业务 API 的安全规则,没有保护 Actuator。Spring Boot 2.x/3.x 项目可以使用 EndpointRequest 明确管理端点的授权规则。
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("OPS")
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}如果健康检查需要匿名访问,可以只放开 health,并控制输出细节:
management:
endpoint:
health:
show-details: never不要在公网暴露包含组件状态、数据库状态、缓存状态、消息队列状态的详细健康信息。这些信息对定位内部架构很有帮助,但对外部访问者也同样有价值。
6. 从网关和反向代理侧复核
实际风险经常发生在网关层。例如 Nginx 配置中把所有路径都转发到了后端:
location / {
proxy_pass
}如果后端包含 Actuator,这种配置会把 /actuator/** 一并暴露。更稳妥的做法是在边界层明确拒绝管理路径,或只转发业务前缀。
location ^~ /actuator/ {
return 403;
}
location /api/ {
proxy_pass
}如果使用 Spring Cloud Gateway,也要检查路由谓词是否过宽。例如 Path=/** 需要特别谨慎,最好在网关层增加路径黑名单或只允许明确业务路径。
7. 验证实际访问面
在授权的内部测试环境中,可以对目标服务做最小化验证。建议只验证端点是否存在、是否需要认证、是否输出敏感信息,不要下载大文件或触发高消耗操作。
curl -i
curl -i
curl -i
curl -i 状态码是 200、401、403 还是 404。响应体是否列出了所有可用端点。 是否出现数据库地址、Redis 地址、消息队列地址、内部域名。 是否出现 Token、AccessKey、密码片段、连接串。 是否能通过外部网关访问到同样内容。 测试时建议控制请求频率,不要对 heapdump、threaddump 等端点做批量请求。它们可能带来明显资源消耗,生产环境尤其要谨慎。
敏感端点风险说明
端点 主要风险 建议 /actuator/env可能泄露环境变量、配置项、连接信息 生产环境不对外暴露,必要时强认证 /actuator/configprops泄露配置结构、组件参数 默认关闭 Web 暴露 /actuator/beans泄露 Bean 结构和内部类名 仅内部排障使用 /actuator/mappings暴露接口路由、控制器映射 避免外部访问 /actuator/threaddump泄露线程栈、内部调用链 限制访问并记录审计日志 /actuator/heapdump可能包含内存中的敏感数据,文件体积大 生产环境不建议开放 /actuator/logfile泄露日志、异常、用户请求参数 不通过 Web 暴露 /actuator/prometheus泄露服务指标、接口名称、实例信息 仅允许监控系统访问
加固建议
生产环境可以按以下优先级处理:
- 只暴露必要端点,优先保留
health、info、prometheus。 - 不要使用
include=* 作为长期配置。 - 管理端口与业务端口分离,并在网络层限制访问来源。
- 网关、Ingress、Nginx 层明确阻断
/actuator/** 的外部访问。 - 对非公开端点启用认证授权,建议与运维角色绑定。
- 健康检查不要输出详细组件状态,避免泄露内部依赖。
- 监控抓取路径只允许 Prometheus、APM 等固定来源访问。
- 对配置中心、容器环境变量、部署模板做统一检查,避免环境覆盖导致暴露。
- 将 Actuator 暴露检查加入上线前安全基线和 CI 检查。
一个相对保守的生产配置示例:
management:
server:
port: 9001
endpoints:
web:
base-path: /actuator
exposure:
include: health,info,prometheus
endpoint:
health:
show-details: never
如果管理端口必须通过集群网络访问,建议配合防火墙、安全组或 Kubernetes NetworkPolicy 做来源限制,而不是只依赖应用层认证。
CI 中的简单检查思路
对于团队项目,可以在 CI 中加入轻量级规则,发现高风险配置时提醒人工复核。例如检测 include=*:
grep -R "management.endpoints.web.exposure.include=.*\*" \
./src ./config ./deploy 2>/dev/null
检测 YAML 中的宽松配置可以结合 yq 或自定义脚本做更准确的解析。简单 grep 会有误报,但作为上线前提醒已经有一定价值。关键是把这类配置纳入工程流程,而不是靠人工临时想起。
注意点
- 不要只看本地配置,线上配置中心和部署模板更接近真实风险。
- 不要认为“内网服务”就一定安全,演练和真实事件中横向访问内网管理端点很常见。
- 不要把路径改名当作安全措施,路径隐藏只能降低误扫概率,不能替代认证和访问控制。
- 不要在日志、健康信息、info 端点里输出版本、Git 分支、构建人、内部域名等过多信息。
- 升级 Spring Boot 后要重新验证 Actuator 行为,端点路径和默认策略可能发生变化。
总结
Actuator 暴露问题的本质不是组件本身不安全,而是管理面和业务面边界没有划清。代码审计时要同时看依赖、配置、认证、端口、网关和部署环境;加固时要遵循最小暴露、网络隔离、强认证、可审计的原则。
如果团队里有大量 Spring Boot 服务,建议把 Actuator 作为安全基线的一部分固定下来:允许哪些端点、哪些环境可访问、哪些来源可访问、谁有权限访问。这样比事后逐个服务排查要可靠得多。

服务器、云资产与权限边界梳理示意
推荐意见