Spring Boot Actuator未授权访问漏洞剖析与安全加固实践

发布时间:2026/9/7 17:40:44
Spring Boot Actuator未授权访问漏洞剖析与安全加固实践 1. Actuator是什么为什么会成为突破口1.1 先搞懂Actuator的定位Spring Boot Actuator是Spring Boot为应用提供的“体检报告”模块。我在实际项目里经常把它比作汽车的仪表盘——它把应用内部运行时的各种状态数据暴露出来比如当前进程的内存使用、线程池情况、环境变量、配置项、日志级别甚至HTTP请求的历史记录。这个模块的设计初衷是给运维和开发人员用的。生产环境下应用跑在服务器上你不能直接登录进去看内存用了多少也不可能翻文件系统去看配置是否生效所以Actuator就通过HTTP接口把这些内部状态“开窗”展示给外部。Spring Boot 2.x以后默认暴露的端点是/actuator/health和/actuator/info其他端点默认不暴露。问题就出在很多开发者不知道哪些端点默认不暴露也不知道暴露出去的端点意味着什么于是在实际部署时手动把management.endpoints.web.exposure.include*配了进去或者盲目照抄网上的配置片段把“全部端点对外开放”这个开关直接打开了。1.2 “未授权访问”到底指什么未授权访问字面意思就是“不需要登录、不需要任何凭证直接通过HTTP请求就能访问到本该受保护的接口”。在Spring Boot Actuator的语境里就是攻击者直接访问http://目标IP:端口/actuator/env就能看到服务器的环境变量、数据库连接串、Redis密码、OSS密钥等敏感信息完全绕过了应用本身的认证体系。这里有一个非常关键的认知偏差很多开发人员觉得“我的应用接口都做了登录校验这个Actuator应该也跟着被保护了”但实际上Actuator的端点是独立于业务代码之外的它由Spring Boot自动配置注册跟Controller层的拦截器、过滤器完全是两条线。我在漏洞排查中接触过好几个案例业务接口全部有JWT鉴权但/actuator路径整个裸奔就是因为团队成员压根不知道这回事。2. 哪些端点最危险泄露了什么2.1 高危端点逐个看Actuator暴露的端点非常多但不是每个都有安全风险。真正危险的有以下几类我把它们整理成了一个速查表方便你在自查时对照参考。端点路径泄露内容严重程度/actuator/env环境变量、数据库账号密码、Redis密码、第三方密钥极高/actuator/heapdumpJVM堆内存快照内含密码字符串、Token、业务数据极高/actuator/trace / httptrace近期HTTP请求记录可能包含请求头中的Authorization高/actuator/mappings所有Controller的URL映射帮助攻击者梳理攻击面高/actuator/beans所有Spring Bean信息暴露应用内部结构中高/actuator/configprops配置类属性可能含敏感配置项高/actuator/loggers日志级别可以动态修改为DEBUG记录敏感数据高/actuator/restart重启应用需开启shutdown类端点中/actuator/shutdown关闭应用默认不暴露若开启等于自毁极高这里最容易被忽略但危害最大的是heapdump。它会把整个JVM的堆内存快照下载下来一个Java进程跑久了堆里全是字符串常量数据库密码、用户Token、内存中的明文数据全都躺在里面。我之前做过一次测试用jhat或者Eclipse MAT打开一个生产环境的heapdump文件搜索password关键字一分钟之内就能翻出好几个内部系统的账号密码。trace端点同样危险它保留的是最近100条默认数量HTTP请求的追踪信息如果这个系统内部做了服务间调用请求头里带着内部认证Token那这些Token就会完整地出现在trace日志里攻击者直接拿这个Token去调内部接口比费劲破解密码快得多。2.2 一场完整的“信息泄露”演示为了让你对危害程度有直观感受我在本地环境搭了一个Spring Boot 2.7.18的测试项目故意把Actuator全部端点暴露出来模拟一个配错了的生产环境。整个过程完全本地化仅用于安全科普验证。第一步在application.yml里配了这样的内容management: endpoints: web: exposure: include: *然后启动应用访问http://localhost:8080/actuator/env页面直接返回了一大段JSON。里面有一项是applicationConfig: [classpath:/application.yml]点进去能看到整个配置文件中所有属性的明文值。我测试时特意在配置文件里写了一个假数据库密码db_password_123结果原样出现在响应里。更让我意外的是/actuator/heapdump这个接口直接在浏览器里访问就会自动下载一个bin格式的文件大小取决于应用内存占用。我当时那个测试应用堆内存也就200多MB下载后我用MAT工具打开全局搜索password定位到了十几个包含敏感信息的字符串对象其中就有配置文件里的数据库密码和一段模拟的JWT密钥。整个过程用时不到五分钟没有用到任何扫描工具就是浏览器访问几个URL。这说明了问题的严重性未授权访问漏洞的利用成本极低不需要任何技术门槛只要知道路径就能拿数据。3. 修复与加固的完整方案3.1 方案A根本性解法——关闭不必要的端点修复Actuator未授权访问最简单粗暴的方式就是关掉不需要的端点。对于一个普通的业务服务其实health和info两个端点已经能满足绝大多数监控需求。其他端点尤其是env、beans、configprops、heapdump、trace在日常运行中根本用不上直接禁掉是最稳妥的。在application.yml里这样配置management: endpoints: web: exposure: include: health,info注意一个细节Spring Boot 2.x的include和exclude属性是支持同时配置的如果因为某些原因必须开启部分端点推荐用白名单的方式只列出需要的端点而不要用exclude: *或者include: *这种极端写法。我在代码评审里看到过很多次include: *加上exclude: env,heapdump的配置这种做法是很不推荐的——原因很简单Spring Boot的版本升级会带来端点名称变化你根本没法保证exclude列表能覆盖所有新版新增的高危端点。3.2 方案B用Security做一层真正的鉴权如果监控平台确实需要读取多个端点直接全关不行那就必须上认证。Spring Boot官方推荐的方案是引入spring-boot-starter-security给Actuator端点加一层HTTP Basic认证或者基于角色的访问控制。先引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency然后在配置里指定端点访问的用户名密码spring: security: user: name: actuator password: 强密码请替换这样配置之后访问/actuator/**任意端点时都会弹出HTTP Basic认证框需要输入用户名密码。注意这层认证是加在Spring Security过滤器链上的只对通过DispatcherServlet分发的请求生效。如果你的项目里还有其他全局拦截器需要确认过滤器的执行顺序避免出现Security校验被绕过的情况。如果项目里已经用了Spring Security做业务登录那就需要单独配置Actuator端点的权限规则Configuration public class ActuatorSecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.requestMatcher(EndpointRequest.toAnyEndpoint()) .authorizeRequests() .anyRequest().hasRole(ADMIN); return http.build(); } }这种方式的好处是业务接口走原有的JWT或Session认证Actuator端点单独走一套角色控制互不干扰。我在实际项目中更推荐这种隔离方案比统一加一个全局过滤器要清爽。3.3 方案C网络层与反向代理兜底除了在应用内做防御网络层的隔离也是非常重要的兜底手段。生产环境的运维规范里Actuator端点根本不应该对公网开放。合理的方式有两种第一种是通过防火墙或者安全组规则只允许监控系统所在的内网IP访问/actuator/**路径第二种是在Nginx层直接拦截用Nginx做一层路径级别的访问控制。Nginx配置示例location ~ ^/actuator/(env|heapdump|trace|mappings|beans) { deny all; return 403; } location /actuator/ { allow 10.0.0.0/8; deny all; proxy_pass http://spring-boot-app:8080; }这个配置的意思是高危端点env、heapdump、trace、mappings、beans直接返回403禁止访问其余Actuator端点只允许内网IP访问其他来源一律拒绝。这种网络层面的限制可以跟应用内认证叠加使用形成纵深防御。我在给多个团队做安全加固培训时经常讲一个理念不要指望一层的防护做到绝对安全。就算你在应用层加了认证万一Spring Security的配置被人手滑改坏了呢万一框架版本有CVE呢网络层的ACL是最朴素的兜底方案只要网络规划合理攻击者连请求都到不了应用。4. 常见问题与排查心得4.1 明明配置了include只开放health为什么/actuator还是能访问这个问题我在技术社区里看到过好多次。不少人配置了include: health,info结果/actuator根路径依然能访问返回一个端点列表页或者404。先说结论/actuator根路径能访问在Spring Boot 2.x中默认是会返回当前所有已暴露端点的链接列表但这本身不算漏洞因为列表里只有路径名没有敏感数据。真正需要担心的是/actuator/env这种子路径是否也返回了数据。如果子路径能访问到数据排查思路是这样的第一检查项目里是否引入了其他监控组件比如micrometer的相关依赖这类依赖会自动注册额外的Web端点第二检查management.endpoints.web.exposure.include配置是否真的生效可以在启动日志中搜索Exposing X endpoint(s) beneath base path /actuator这行日志看看到底暴露了哪些端点第三看项目里是否有自定义的Endpoint注解类这类自定义端点不受include的完全控制需要单独配置exposure。4.2 关于heapdump的实战教训我在一次内部的攻防演练中负责攻击方和防守方两边的工作。防守方系统只开启了health和heapdump两个端点理由是监控平台需要定期拉堆内存快照分析内存泄漏。结果实战时攻击方直接下载了heapdump用strings命令分析了一下就拿到了测试环境专用数据库的明文密码——因为开发人员图省事把数据库密码写在了代码常量里JVM启动时这个字符串就一直驻留在堆内存中。这件事给我的教训很深。如果你的团队确实需要开启heapdump端点做内存分析至少要做到以下几点该端点必须加认证不能裸露在公网下载的heapdump文件不能存放在Web目录下分析完的heapdump文件要及时删除不能一直留在服务器上如果可能优先用jmap命令在服务器本机生成堆快照比通过HTTP下载然后传输要安全得多4.3 开发环境要不要也保持配置一致很多团队的生产环境改得很规范但开发环境就随意很多。我个人强烈建议开发环境的Actuator配置也要跟生产环境保持一致不要觉得“反正开发环境别人访问不到”。理由有两个。第一开发环境的代码和配置经常跟生产环境保持同步如果开发环境用include: *代码提交到代码仓库后很容易被误带到生产环境或者被后来接手的人“参考”着这么配。第二现在很多公司项目会通过反向代理将开发环境暴露给外部合作伙伴联调你以为的“内网开发环境”实际上可能早就在公网可访问范围内了。我在团队里推动了这样一条规范所有Spring Boot项目的application.yml模板里Actuator的配置默认就是include: health,info要开启其他端点必须走变更审批流程。这样从源头上拉高了漏洞出现的门槛比事后漏洞修复省事得多。4.4 一个容易被忽略的版本坑Spring Boot 1.x和2.x的Actuator配置方式差异很大。1.x的端点路径是/env、/health、/beans这种不带/actuator前缀的形式配置属性是management.endpoints.shutdown.enabled、management.security.enabled。从2.x开始才引入/actuator前缀和management.endpoints.web.exposure体系。如果你维护的是老项目排查问题时一定要先确认自己的Spring Boot版本。另外Spring Boot 2.0到2.4之间的配置有些小变动比如management.security.enabled这个属性在2.x中直接被移除了改为依赖Spring Security配置来控制访问。我见过有开发者拿着网上1.x时代的配置片段直接贴到2.x项目里结果management.security.enabledfalse根本没生效还以为自己的端点“受保护了”。4.5 如何快速自查一个站点是否存在该漏洞如果你需要排查一个已知的系统是否存在Actuator未授权访问可以先用手工方式快速验证。访问/actuator路径看返回的JSON或者页面状态码。接着访问/actuator/env或/actuator/health如果/actuator/health返回了详细的组件状态信息比如数据库是否可达、Redis是否连接说明至少health端点是开放的要进一步确认其他端点是否也开放。这里有一个不太一样的小技巧即使env端点被关闭很多应用依然可以访问到/actuator/mappings而这个端点在分析应用结构时非常有用所以不要只测env一个端点就得出结论。批量资产扫描时可以用简单的HTTP探测脚本遍历常见路径重点关注env、heapdump、trace这几个特征明显的路径它们的状态码和响应内容可以帮助快速判断是否存在未授权访问。5. 最后的几点实操心法回顾我接触过的Spring Boot项目Actuator未授权访问这个漏洞之所以频频出现技术层面的原因反而是次要的更多是流程和管理上的漏洞。很多团队压根没有一个“开发完自查安全配置”的步骤代码评审也只关注业务逻辑完全没人检查application.yml里的Actuator配置。我个人的习惯是在所有Spring Boot项目的启动类里加一个启动时的安全检查逻辑。在ApplicationRunner中检测当前激活的profile和management.endpoints.web.exposure.include配置如果当前是prod环境但暴露了高危端点就直接打印一条醒目的警告日志甚至在关键场景下直接抛异常阻止启动。这样做虽然略显粗暴但能有效避免配置被带到生产环境。再分享一个监控场景下的小技巧。如果你确实需要对外暴露一些端点给监控系统使用不要直接暴露原生Actuator端点可以在项目里写一个自定义的聚合接口由你的代码主动调用Actuator的内部API然后把需要展示的数据二次加工后返回给监控平台。这样既拿到了监控数据又不需要把框架的原生接口开出去攻击面一下子就缩小了很多。我在实际使用中发现Actuator本身是个非常优秀的模块问题从来不在工具本身而在于使用的人对它缺少敬畏。希望这篇基于实际踩坑经验的分享能让你在配置Spring Boot项目时多留个心眼至少动手之前先问问自己这几个端点真的需要暴露吗暴露之后谁能访问到这两个问题想清楚了大部分漏洞其实都能从源头规避掉。

相关新闻