Spring Boot Actuator 暴露 heapdump内存里的密码可能全漏了线上开了 Actuator本来是为了方便排查问题。结果/actuator/heapdump也暴露出去了。一份堆转储文件下载下来数据库连接串、Redis 密码、Token、用户请求参数都可能躺在里面。一、事故现场有个项目为了方便线上排查开了 Spring Boot Actuator。配置大概是这样management:endpoints:web:exposure:include:*开发同学当时的想法很简单先全部打开线上排查方便一点。结果某天安全扫描扫出来/actuator/env /actuator/metrics /actuator/heapdump /actuator/threaddump这些端点都能访问。其中最危险的是/actuator/heapdump这个接口会导出 JVM 当前堆内存快照。换句话说JVM 里活着的对象它都可能出现在 heapdump 里。这就不是“暴露一点监控信息”的问题了。这是把应用内存打包交出去了。二、heapdump 里到底有什么很多人低估了 heapdump 的敏感程度。它不是普通日志。它是 JVM 堆内存快照。里面可能包含配置对象 数据库连接信息 Redis 连接信息 MQ 连接信息 第三方 API Token JWT / Session / Cookie 用户请求参数 接口返回数据 缓存对象 业务实体 异常堆栈 临时字符串比如项目里有这种配置spring:datasource:url:jdbc:mysql://10.0.0.12:3306/order_dbusername:order_userpassword:Abc123456redis:host:10.0.0.20password:redis-secret这些配置在应用启动后通常会被绑定成 Java 对象。只要对象还在堆里就有可能出现在 heapdump 文件中。再比如请求里带了 TokenAuthorization: Bearer eyJhbGciOiJIUzI1NiJ9...或者用户刚提交过敏感参数{mobile:13800000000,idCard:xxx,password:xxx}这些字符串如果还没被 GC也可能在堆快照里被找到。所以 heapdump 暴露的风险不是“看一下内存占用”。而是把应用运行时的敏感数据一起暴露了。三、为什么很多项目会误开最常见的是这行配置management:endpoints:web:exposure:include:*这表示暴露所有 Web 端点。开发环境这么配问题不大。但如果生产也这么配就危险了。还有一种写法management:endpoints:web:exposure:include:health,info,metrics,env,heapdump,threaddump看起来比*收敛了一点。但heapdump、env、threaddump仍然是高风险端点。尤其是这些端点风险/actuator/heapdump导出 JVM 堆内存可能包含密码、Token、用户数据/actuator/env暴露环境变量、配置项和配置来源旧版本或配置不当时可能泄露敏感值/actuator/configprops暴露配置绑定对象旧版本或配置不当时可能泄露敏感值/actuator/threaddump暴露线程栈、类名、方法名、业务路径/actuator/logfile暴露日志内容/actuator/mappings暴露接口路由这些东西对开发排查很方便。对攻击者也很方便。这里要补一个版本细节。较新的 Spring Boot 对/actuator/env、/actuator/configprops这类端点默认会做敏感值脱敏很多密码字段不会直接明文展示。但这不代表它们就可以放心暴露。因为它们仍然会暴露配置结构、属性名、配置来源、组件信息和内部实现细节。如果项目使用旧版本、改过脱敏规则或者把show-values配成了always敏感值仍然可能被打出来。而/actuator/heapdump的风险更直接。它导出的是堆内存快照不是经过脱敏处理的配置视图。四、Actuator 默认不是原罪乱暴露才是Actuator 本身不是问题。它是非常好用的生产诊断工具。问题在于暴露范围太大 没有鉴权 直接挂公网 生产和开发共用一套配置安全的做法不是“永远不用 Actuator”。而是生产环境只开放必要端点。比如最小配置management:endpoints:web:exposure:include:health,info如果接入 Prometheusmanagement:endpoints:web:exposure:include:health,info,prometheus不要为了省事写include:*这行配置在生产环境里非常刺眼。五、生产环境应该怎么配1. 只暴露必要端点推荐management:endpoints:web:exposure:include:health,info,prometheus不推荐management:endpoints:web:exposure:include:*如果没有监控采集需求甚至可以只留management:endpoints:web:exposure:include:health2. health 不要暴露过多细节很多项目会开management:endpoint:health:show-details:always这会把很多健康检查细节暴露出去。生产环境更建议management:endpoint:health:show-details:never或者只对已认证用户展示management:endpoint:health:show-details:when_authorized3. 管理端口和业务端口分开可以把 Actuator 放到单独端口management:server:port:9090然后通过安全组、内网、防火墙限制访问。比如业务端口 8080对外开放 管理端口 9090只允许内网监控系统访问这样即使业务接口暴露公网管理端点也不会跟着裸奔。4. 加鉴权如果管理端点必须通过 HTTP 访问至少要加鉴权。比如只允许管理员角色访问ConfigurationpublicclassActuatorSecurityConfig{BeanSecurityFilterChainactuatorSecurityFilterChain(HttpSecurityhttp)throwsException{http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(auth-auth.requestMatchers(EndpointRequest.to(health,info)).permitAll().anyRequest().hasRole(ACTUATOR_ADMIN)).httpBasic(Customizer.withDefaults());returnhttp.build();}}具体写法会随 Spring Security 版本变化但原则不变非公开端点必须鉴权。5. 明确关闭高危端点如果不需要 heapdump可以显式关掉management:endpoint:heapdump:enabled:false也可以关闭其他高危端点management:endpoint:env:enabled:falseconfigprops:enabled:falsethreaddump:enabled:falselogfile:enabled:false注意端点“启用”和“暴露”是两回事。一个端点可能在应用内部启用了但没有通过 Web 暴露。在较新的 Spring Boot 版本里还可以额外通过端点访问级别控制某个端点是不可访问、只读还是允许完整访问。不同版本的配置项名字会有差异落地时要按自己项目的 Spring Boot 版本确认。生产环境要同时关注enabled exposure access network access authentication如果确实需要临时开放env或configprops给内网排查至少不要在生产环境使用management:endpoint:env:show-values:alwaysconfigprops:show-values:always更稳的做法是保持敏感值不展示或者只对已认证、已授权的用户展示。六、已经暴露过 heapdump怎么办如果你发现生产环境曾经暴露过/actuator/heapdump不要只把配置改掉就结束。建议按事故处理。1. 立即下线暴露端点先改配置management:endpoints:web:exposure:include:health,info,prometheusendpoint:heapdump:enabled:false同时确认网关、Nginx、安全组没有继续放行。2. 检查访问日志查这些路径有没有被访问过/actuator /actuator/heapdump /actuator/env /actuator/configprops /actuator/threaddump /actuator/logfile重点看访问 IP 访问时间 响应状态码 响应大小 是否有异常下载流量如果/actuator/heapdump返回过大文件就要高度警惕。3. 轮换密钥和密码heapdump 里可能出现这些敏感信息数据库密码 Redis 密码 MQ 密码 对象存储密钥 第三方 API Token JWT 签名密钥 内部服务调用凭证如果确认有外部访问建议轮换相关凭证。不要赌“没人会分析那个文件”。4. 检查异常登录和异常调用如果数据库、Redis、对象存储、第三方平台有审计日志要一起看。重点看陌生 IP 登录 异常时间段访问 大量读取 失败重试 权限变更 新增账号Actuator 泄露本身只是入口。真正的损失可能发生在后面。七、团队规范生产 Actuator 最小化如果让我给团队定一条规范我会这样写生产环境禁止 exposure.include* 生产环境默认只开放 health、info、prometheus heapdump、threaddump、logfile 不允许公网访问 env、configprops 不允许公网访问确需内网开放时也不要展示敏感值 管理端口必须走内网或鉴权 所有 Actuator 配置必须区分 dev/test/prod配置可以分环境。开发环境# application-dev.ymlmanagement:endpoints:web:exposure:include:*endpoint:health:show-details:always生产环境# application-prod.ymlmanagement:endpoints:web:exposure:include:health,info,prometheusendpoint:health:show-details:neverheapdump:enabled:falseenv:enabled:falseconfigprops:enabled:falsethreaddump:enabled:falselogfile:enabled:false这才是比较稳的方式。不要让开发配置跟着一起上生产。八、上线前 checklist上线前看到 Actuator建议过一遍这个表。检查项风险建议是否配置include: *所有端点暴露生产禁止是否暴露heapdump堆内存泄露关闭或仅内网鉴权是否暴露env配置结构、环境变量和敏感值泄露风险关闭确需开放时鉴权并避免show-values: always是否暴露configprops配置对象和敏感值泄露风险关闭确需开放时鉴权并避免show-values: always是否暴露logfile日志敏感信息泄露关闭管理端口是否公网可访问被扫描命中内网隔离health 是否展示详情泄露组件信息prod 用neverdev/prod 配置是否隔离开发配置上生产分环境配置是否有访问日志暴露后难追踪网关/Nginx 留日志九、总结Actuator 是好工具。但生产环境里它不是给所有人看的。尤其是/actuator/heapdump。它导出的不是普通监控数据而是 JVM 堆内存快照。里面可能有密码 Token 连接串 用户数据 业务对象 请求参数所以生产环境记住三句话不要include: *。不要把管理端点挂公网。不要无鉴权暴露 heapdump、env、configprops、logfile 这类高危端点。下一篇准备写Async 默认执行器又炸了SimpleAsyncTaskExecutor 为什么不是线程池。如果你也在排查 Java 后端线上问题可以关注公众号云技纵横。这个系列会持续更新 Spring 事务、线程池、JVM、MySQL、Redis、MQ 的真实踩坑复现。