尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring Boot Actuator未授权访问漏洞:原理、危害与修复方案

Spring Boot Actuator未授权访问漏洞:原理、危害与修复方案 最近做安全巡检漏洞扫描报告里又躺了一条“Spring Boot Actuator未授权访问漏洞【原理扫描】”。这大概是Spring Boot项目里最常见的告警之一很多开发同学看到“原理扫描”四个字就当误报忽略了但这恰恰是最容易翻车的漏洞类型。这篇文章我从漏洞原理、危害场景、修复方案、验证方法到踩坑实录完整复盘一遍这类漏洞的处理过程希望对正在做安全整改的你有所帮助。先说结论这种漏洞不修复轻则泄露配置信息和堆内存快照重则被拿数据库密码、Redis密码、内部接口调用链甚至直接被关停服务。别等扫描器报了“可被利用”才动手到那时候基本已经被打穿了。1. 漏洞原理Actuator为什么会让服务“裸奔”1.1 Actuator端点到底是什么Spring Boot Actuator是框架自带的生产级监控组件它的作用是让应用在运行期对外暴露内部状态信息。默认情况下Spring Boot 2.x的端点前缀是/actuator1.x则是根路径或/下的一级端点。按风险级别我把关键端点分成几类端点泄露内容危害级别/actuator/env环境变量、数据库连接串、Redis密码、自定义配置项严重/actuator/heapdumpJVM堆内存快照里面可能有密码、Token、用户数据严重/actuator/configpropsConfigurationProperties配置项包含加密盐、密钥等严重/actuator/mappings应用全部URL映射关系攻击者据此分析攻击面高/actuator/beans所有Spring Bean信息暴露组件结构和依赖关系中/actuator/threaddump线程快照可能泄露业务线程上下文中/actuator/loggers可动态修改日志级别中/actuator/shutdown关闭应用1.x默认开启严重你可以把Actuator理解成一套“汽车仪表盘”接口。本来仪表盘是给司机看的但如果车门没锁任何人都能拉开车门看仪表盘甚至还能动方向盘。heapdump和env这两个接口相当于把汽车的行车记录仪和钥匙盒都敞开了。1.2 未授权访问是怎么产生的Spring Boot 1.x时代Actuator默认把大多数端点暴露在web上且不需要认证这是历史欠账。Spring Boot 2.x开始默认只暴露health和info看起来安全了不少但实际项目中依然存在大量未授权访问问题原因基本都是这几种第一是开发阶段为了调试方便配置了management.endpoints.web.exposure.include: *上线时忘了改。第二是老项目从1.x升级到2.x配置沿用旧逻辑没有做安全检查。第三是服务部署在内网认为“内网是安全的”结果内网一台机器被攻破后横向移动Actuator成了跳板。第四是引入了Spring Security但SecurityFilterChain只保护了业务接口没有覆盖/actuator/**。1.3 “原理扫描”到底是什么意思很多朋友看到扫描报告里的“【原理扫描】”标注以为只是扫描器根据版本号“猜”出来的并不代表真实存在漏洞于是直接忽略。这里有个认知误区原理扫描确实是扫描器基于响应特征做的“非攻击性验证”没有做真正的漏洞利用但它判定的是“这一类配置存在风险”而不是空穴来风。举个例子扫描器请求/actuator/env如果返回HTTP 200且响应体包含propertySources这样的JSON字段扫描器就会判定存在未授权访问。注意它不做后续的“读取数据库密码并连接数据库”这类操作所以标注为“原理扫描”。但问题在于如果这个接口对外可达攻击者完全可以手动完成后面的利用步骤扫描器不做的攻击者会做。我在处理过的真实案例里见过最典型的就是扫描器报告“原理扫描”开发团队不以为意三个月后内网渗透测试人员通过heapdump拿到了完整的内存中的数据库密码直接登录了生产库。所以只要报告里有这条无论标注是什么都建议按真实漏洞对待。2. 动手修复前的检查与准备2.1 三步确认当前暴露面修复不能直接改配置了事先花几分钟确认一下现状避免改完之后把监控系统搞挂。第一步验证Actuator是否真的对外暴露。用命令行直接请求一下curl -i http://目标IP:端口/actuator如果返回的是JSON数据里面有_links字段说明端点对外可访问。如果返回404说明默认路径下没有暴露但还要检查一下是否自定义了路径后缀。第二步检查哪些端点处于开放状态。可以逐个请求比如curl -i http://目标IP:端口/actuator/env curl -i http://目标IP:端口/actuator/heapdump curl -i http://目标IP:端口/actuator/mappings或者直接看项目配置文件grep -r management application*.yml重点关注include、expose、enabled这几类配置。第三步确认业务系统哪些端点真的在用。比如K8s探活要用healthPrometheus监控要用prometheusSpring Cloud服务注册可能要info。这一步必须在改动前和运维、监控团队核实否则改完以后健康检查直接挂了那就是一次事故。2.2 修复方案选型思路Actuator修复不是一味地把所有端点全关掉而是遵循“最小暴露原则”只开放业务必需的最少端点并且对敏感端点增加认证和网络访问控制。整体上我习惯把修复分成四个层面按优先级排序应用内配置层关闭不需要的端点只暴露最小必要集。应用内认证层引入Spring Security对/actuator/**路径做登录鉴权和角色校验。网络访问层通过Nginx、负载均衡、安全组或防火墙限制访问来源IP。版本升级层升级到受支持的Spring Boot版本避免依赖旧版的历史默认值。对于大多数项目我推荐“应用内配置层 应用内认证层”的组合网络层作为兜底。只靠安全组限制也有意义但如果内网本身已经被渗透安全组形同虚设。反过来只靠应用内认证如果应用本身有其他漏洞也可能被绕过。多层防护的核心思路是即使某一层被突破其他层还能挡住。2.3 修复前的一个“坑”要提前踩这里先提醒一个很多人忽视的问题如果项目里已经引入了Spring Security但之前没有对Actuator做权限配置那么修复时只需要在现有Security配置上增加路径规则改动很小。但如果没有引入Spring Security现在引入要特别注意它会把所有未放行的接口全部拦截掉包括业务接口。这个问题在实战中非常常见我在后面的“常见问题”部分会细说。3. 核心修复实操3.1 基础方案按需关闭端点最小化暴露仅修改application.yml就能挡住大部分风险。核心配置如下management: endpoints: # 所有端点默认不启用 enabled-by-default: false web: # 只通过Web暴露这2个端点 exposure: include: health,info endpoint: health: enabled: true info: enabled: true # 敏感端点显式禁用即使被include也禁用 env: enabled: false heapdump: enabled: false shutdown: enabled: false这套配置的关键在于enabled-by-default: false先把所有端点关掉然后用include: health,info只打开必要的两个。我见过很多团队用include: *然后靠exclude去屏蔽这种思路也能用但容易漏。比如你exclude了env但下次升级版本多出来的新端点可能不在exclude列表里风险面就扩大了。从默认关闭到按需开启这才是保险的配置方式。另外两个建议一起做第一把Actuator的管理端口和业务端口分开给管理端点配置独立端口management: server: port: 9090 address: 127.0.0.1这个配置的意思是实现在某个独立端口比如9090上并且只绑定本机回环地址外部完全无法通过网络访问。如果监控系统部署在同一台机器上直接访问本机回环地址即可。第二修改默认的/actuator路径换成一个不明显的路径management: endpoints: web: base-path: /manage注意修改路径不是安全措施。它的作用只是增加被脚本扫描器命中的难度属于“信号干扰”型防御。面对定向攻击者路径很快就会被摸出来。所以基础方案的正确姿势是端口分离 路径混淆 端点最小化。三个手段叠加而不是只靠一个。3.2 进阶方案Spring Security强制认证如果服务需要对外暴露管理端点或者集群里的其他组件需要远程获取监控数据那就必须在应用内加上认证授权。最常用的方式是接入Spring Security的HTTP Basic认证或表单登录配合角色控制。引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency补充说明如果项目本身没有使用Spring Security直接加依赖后Spring Boot会生成一个默认用户user密码在启动日志中业务接口也会被拦截。所以必须马上配置自己的SecurityFilterChain把业务接口放行只对/actuator/**做保护。在Spring Boot 2.7 / 3.x推荐的配置方式是使用SecurityFilterChainConfiguration EnableWebSecurity public class ActuatorSecurityConfig { Bean Order(1) public SecurityFilterChain actuatorFilterChain(HttpSecurity http) throws Exception { http .securityMatcher(/actuator/**) .authorizeHttpRequests(auth - auth .anyRequest().hasRole(ADMIN) ) .httpBasic(Customizer.withDefaults()) .csrf(csrf - csrf.disable()); return http.build(); } Bean Order(2) public SecurityFilterChain appFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth - auth .requestMatchers(/login, /static/**, /public/**).permitAll() .anyRequest().authenticated() ) .formLogin(Customizer.withDefaults()); return http.build(); } Bean public UserDetailsService users() { UserDetails admin User.withDefaultPasswordEncoder() .username(monitor) .password(${ACTUATOR_ADMIN_PASSWORD}) .roles(ADMIN) .build(); return new InMemoryUserDetailsManager(admin); } }关键点在Order(1)和securityMatcher(/actuator/**)。这个过滤器链只处理Actuator路径优先匹配命中后走HTTP Basic认证角色必须是ADMIN。Order(2)的过滤器链处理其他业务路径按原来的业务规则放行。密码这一块要注意示例里用了User.withDefaultPasswordEncoder()这个方式仅适用于演示和本地环境。生产环境一定要用BCryptPasswordEncoder密码通过环境变量或配置中心注入不要写死在代码和配置文件里。这里补充说明一下老项目的情况。如果你的项目还是Spring Boot 2.6及以下版本并且用了继承WebSecurityConfigurerAdapter的写法修复方式类似只需在configure(HttpSecurity http)里加一段http .authorizeRequests() .antMatchers(/actuator/health, /actuator/info).permitAll() .antMatchers(/actuator/**).hasRole(ADMIN) .and() .httpBasic();在升级到2.7或3.x时WebSecurityConfigurerAdapter已废弃需要迁移到上面说的SecurityFilterChain方式。3.3 网络层加固Nginx和安全组双保险应用层已经加上了认证网络层仍然建议做限制特别是当服务直接暴露在公网或不可信内网时。在Nginx层拦截外部访问只允许内网网段访问Actuator路径location ~ ^/actuator/ { allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; proxy_pass http://app_upstream; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }这段配置的作用是来自内网的请求通过反向代理转发其他来源直接返回403。注意在Nginx里要放在server块内并且放在其他location的前面避免被通配规则先命中。同时在云安全组或防火墙层面如果Actuator使用了独立管理端口就只放行对应网段的入站流量。举个例子如果业务端口是8080管理端口是9090安全组规则应该是8080对公网开放9090仅对监控服务器IP和运维跳板机IP开放。网络层限制的定位是兜底。它的价值在于即使应用层配置被绕过或者代码有逻辑漏洞攻击者网络层面就过不来。而应用层认证的价值在于网络层被误放行时认证还能挡一道。两者不是替代关系是接力关系。3.4 老版本项目怎么修如果是Spring Boot 1.x的项目处理方式会稍有不同。1.x没有management.endpoints.web.exposure.include这套配置它的默认行为是暴露除shutdown以外的所有端点且不需要认证。修复方式有以下几种第一种逐个禁用敏感端点endpoints: env: enabled: false heapdump: enabled: false beans: enabled: false mappings: enabled: false shutdown: enabled: true注意1.x里有一个默认开启的/health和/info一般业务要用可以保留但/health默认会展示部分磁盘信息建议配置endpoints.health.sensitive: true让它只返回简单的UP/DOWN状态。第二种在项目无法立即改造的情况下先用管理端口隔离设置独立的management.port然后在网络层严格限制这个端口的来源IP。第三种如果条件允许优先规划升级到Spring Boot 2.7或3.x因为老版本不仅Actuator有漏洞还有很多其他已知安全风险。3.5 升级到新版时的额外配置如果你的项目计划借这次修复升级Spring Boot版本顺便提醒几个注意点Spring Boot 2.x到3.x变化比较大Actuator配置项基本保持一致但Spring Security 6中WebSecurityConfigurerAdapter已彻底移除必须使用SecurityFilterChain。另外3.x基于Jakarta EE如果项目里有依赖旧版Servlet API的组件需要一并处理。Spring Boot 2.7版本的management.endpoints.web.exposure.include行为没变但新增了一些端点。如果使用include: *建议在升级后重新审视哪些端点被暴露了不要盲目沿用旧配置。4. 修复验证与常见问题排查4.1 修复效果要这样验证配置改完、服务重启之后不能只看扫描报告要亲自动手验证一遍。我把验证步骤整理成一份操作清单# 1. 未认证访问关键端点应该返回401/403 curl -i http://localhost:8080/actuator/env # 2. 认证后访问带正确的用户名密码 curl -u monitor:你的密码 http://localhost:8080/actuator/health # 3. 检查暴露的端点列表确认只剩最小必要集 curl -u monitor:你的密码 http://localhost:8080/actuator # 4. 独立端口模式下确认业务端口访问不到管理端点 curl -i http://localhost:8080/manage/health如果第1步返回的是200和JSON数据说明修复没生效排查下面几类问题。如果第4步在没有绑定127.0.0.1的情况下返回403或超时说明网络层或端口限制是生效的这符合预期。除了手动验证还要检查应用日志。Spring Security的认证失败会在日志里留下Failed to authenticate记录健康检查的探测请求也会有访问记录。修复上线后建议观察两天确认监控系统能正常拉取数据业务接口不受影响。4.2 常见问题速查表这一节整理了我在处理过程中遇到的典型问题直接做成表格方便对照排查问题现象可能原因处理方法配置了enabled-by-default: false端点还是能访问include和enabled是两层控制include会强制暴露指定端点在include里移除该端点或者给该端点单独设置enabled: false只改了include但端点返回404路径前缀不对或Spring Boot版本配置项名称不同确认base-path1.x和2.x配置项差异较大先查版本再改配置引入Spring Security后业务接口全部401过滤器链把所有请求都拦截了调整SecurityFilterChain给业务路径加permitAll()或authenticated()规则修复后扫描器依然报漏洞只改了应用配置但服务没重启或存在多个实例、负载均衡后面有旧节点全量重启所有实例重新扫描验证确认没有节点被配置中心覆盖配置被Nacos/配置中心远程覆盖远端配置的优先级高于本地application.yml修改配置中心的对应配置并统一规范管理Docker/K8s环境配置不生效环境变量SPRING_APPLICATION_JSON或环境变量优先级高于配置文件检查环境变量、ConfigMap、启动参数统一在编排层修改端口已分离但外网还能访问管理端口安全组或防火墙未限制、Nginx未配置拦截在云控制台/防火墙检查入站规则关闭管理端口公网访问密码写在application.yml里扫描器或代码泄露后直接获取配置管理不规范改为环境变量或密钥管理组件注入4.3 实际排查案例一次Security配置导致的“业务全挂”有一次帮一个团队处理Actuator漏洞引入Spring Security后测试环境所有业务接口全部返回401。排查后发现问题出在过滤器链的配置方式上团队只是加了个WebSecurityConfigurerAdapter没有区分Actuator路径和业务路径结果所有请求都要认证。这类问题的本质是Spring Security的过滤器链是全局的你配置的规则会作用于所有请求。解决办法就是前面提到的OrdersecurityMatcher拆分成两条过滤器链一条管/actuator/**另一条管业务。这里特别注意Actuator过滤器链要放在Order(1)优先匹配否则会被业务过滤器链抢先拦截。4.4 修复过程中的一些实践经验有几个习惯是在不停踩坑之后才养成的分享出来供参考修复前先备份原配置文件并且记录一下原配置的变更点。这样回滚方便排查问题时也能通过对比快速定位。改配置时不要把Spring Boot的配置和业务配置混在一起。建议在配置中心单独建一个actuator-security命名空间独立管理Actuator相关配置这样即使业务配置频繁调整也不会带偏安全配置。修复完成之后不要只扫一次就结束。我建议在修复后第1天、第7天、第30天各扫一次因为有些配置会被后续的发布流程覆盖回去特别是那种“开发为了排查问题临时改配置然后忘记改回来”的情况特别普遍。4.5 留一个“旁路逃生通道”这个技巧不一定适合所有团队但确实能在关键时刻避免事故在完全禁用掉所有敏感端点之前先确认运维监控系统的数据采集通路。我在处理一件事时直接把/actuator/env和/actuator/heapdump禁用了结果第二天监控平台告警说指标采集失败——原来是监控平台通过/actuator/metrics拉数据的而我在include里没有放行metrics。所以稳妥的做法是先确认监控系统需要哪些端点把这些端点加入include白名单其他全部禁用。如果监控系统暂时不可用宁可先保留health和info这两个低风险端点再逐步收口。5. 修复效果评估与长效保持5.1 修复完成的标准是什么很多人认为“扫描器不报漏洞”就是修复完成这个标准不够严谨。我建议用下面这份验收清单来定义“完成”未认证请求/actuator/env、/actuator/heapdump等敏感端点返回401/403或404。暴露的端点列表里只剩health、info等最小必要集没有*通配暴露。认证后的请求能正常访问业务需要的端点监控系统指标采集正常。独立管理端口配置下业务端口无法访问管理端点。安全日志中有对应的未授权访问拒绝记录便于事后审计。扫描器复扫不再报同样的问题。把这六条逐一过一遍再确认验收。5.2 后续如何防止“修了又坏”安全整改的难点在于“保持”。很多漏洞修好之后几周后又因为一次发布、一次配置调整重新暴露。常见的有三种反复路径第一种是本地配置被覆盖开发本地跑起来时改了配置提交代码时自定义配置被版本管理工具覆盖。第二种是发布流程不规范有人手动改了生产环境的配置没有同步到版本库。第三种是配置中心权限过大开发环境配置直接同步到了生产环境。要防止这些问题除了规范发布流程还可以把Actuator配置纳入自动化检查。比如在CI流水线里加一个步骤扫描构建产物的配置文件检查是否存在include: *、是否显式禁用了env和heapdump。写一个简单的脚本就能做不用额外引入复杂工具#!/bin/bash # 检查构建产物中是否包含危险Actuator配置 if grep -r management.endpoints.web.exposure.include.*\* target/classes/ 2/dev/null; then echo 检测到Actuator通配暴露配置构建失败 exit 1 fi echo Actuator配置检查通过 exit 0这个脚本虽然简单但能在“配置上线前”拦截一次问题减少线上返工的概率。6. 最后再分享一点实际经验处理Actuator漏洞这几年我自己的体会是这条漏洞被标记为“原理扫描”并不代表风险低恰恰因为它是原理层面的开放攻击者拿到入口之后能做的事太多了。每次做完一套修复我都会花十分钟做一次完整验证包括手动请求各个敏感端点、查看日志、确认监控采集正常。这个过程看起来琐碎但能省掉后面很多麻烦。如果你的项目还没有中招建议现在就检查一下打开/actuator看看返回了什么查一下include配的是什么有没有引入Security却忘了保护Actuator路径。三分钟的事比等到扫描报告标红再处理划算得多。修复的思路总结下来就是六句话先确认暴露面再最小化端点该认证的加认证网络层做兜底验证做到位发布流程防回退。照着这个顺序走这条漏洞基本就不会再找上你。
返回列表