手把手教你用Vulhub复现nacos/CVE-2021-29441和CVE-2021-29442漏洞(附完整POC)

4 阅读9分钟

创作声明

AI创作声明

本文由AI辅助创作,经作者人工审核与修订。内容旨在技术交流与学习,如有疏漏或错误,欢迎指正。

免责声明

本文内容仅供学习与研究用途,不保证完全准确或适用于所有环境。读者依据本文操作所产生的一切后果,作者及平台不承担任何法律责任。请遵守法律法规,勿将技术用于非法目的。

版权声明

本文为原创内容,版权归作者所有。未经授权,禁止商业用途转载。非商业转载请注明出处并保留本声明。

准备工作

Docker的常用命令

docker compose pull #将远程镜像拉取到本地

docker compose up -d #启动容器,并且不包含下载日志

docker ps            #查看开放端口

docker compose logs  #查看日志

docker compose down  #销毁容器

docker compose build #重启容器

docker compose exec web bash  #进入名为web的服务容器并打开 Bash 终端的命令

这里只展示了CVE-2021-29441的部分。

漏洞原理分析

漏洞原理代码流程图

┌─────────────────────────────────────────────────┐
│            Nacos AuthFilter.doFilter()          │
├─────────────────────────────────────────────────┤
│  public void doFilter(...) {                    │
│    // 关键漏洞代码:                            │String userAgent = request.getHeader(        │
│        "User-Agent");                           │
│    if (userAgent != null &&                     │
│        userAgent.contains("Nacos-Server")) {    │
│        // BUG: 直接放行内部请求!               │
│        filterChain.doFilter(request, response); │
│        return;                                  │
│    }                                            │
│    // 正常认证流程...                           │
│  }                                              │
└─────────────────────────────────────────────────┘

CVE-2021-29441 是 Nacos 中的一个 认证绕过漏洞(Authentication Bypass by Spoofing),影响 Nacos < 1.4.1。当启用认证机制 (-Dnacos.core.auth.enabled=true) 时,Nacos 使用 AuthFilter servlet 过滤器来强制执行身份验证,但该过滤器存在一个“后门”,导致认证检查被绕过。其关键点是:

  • 该后门逻辑依赖 User-Agent HTTP 头
  • User-Agent 被认为是可信的(例如 "Nacos-Server"
  • 攻击者可 伪造该头部 来跳过认证
  • 绕过后可以执行任何 Nacos 管理行为,包括服务与配置操作
  • 未授权用户因此获得完全管理权限

换句话说:过滤器本应在请求到达控制器前阻止未认证访问,但后门逻辑错误地将某些 User-Agent 标记为“可信内部请求”,从而直接进入核心逻辑。

攻击场景流程图 + DFD 威胁建模

graph TD
    A[攻击者] --> B[探测目标<br>访问/nacos/v1/auth/users]
    B --> C[返回403 Forbidden]
    C --> D[构造伪造请求]
    D --> E[添加UA头: Nacos-Server]
    E --> F[Nacos AuthFilter]
    
    F --> G{UA检测}
    G -->|检测到Nacos-Server| H[判定为内部请求]
    G -->|未检测到| I[正常认证流程]
    
    H --> J[跳过认证检查]
    J --> K[放行请求]
    
    K --> L[创建新用户]
    K --> M[重置管理员密码]
    K --> N[获取配置文件]
    
    L --> O[权限提升成功]
    M --> O
    N --> P[信息泄露]
    
    style F fill:#ffcccc
    style G fill:#ff9999
    style H fill:#ff6666

攻击者通过伪造 HTTP 请求中的 User-Agent 为 "Nacos-Server"(或其他被错误信任的字符串),触发过滤器绕过逻辑,从而跳过认证检查。该攻击路径不需要凭据,攻击复杂度低。

DFD(数据流图:威胁建模)

[Attacker]
    |
    | (1) HTTP Request w/ Spoofed User-Agent
    v
[Process P1: Nacos AuthFilter]
    |
    | (2) Bypass Check (User-Agent Trusted)
    v
[Process P2: Business Logic]
    |
    | (3) Administrative Actions
    v
[DataStore: Configs & Metadata]


STRIDE 分析

威胁类别是否说明
Spoofing(伪造)攻击者伪造 User-Agent
Tampering⚠️未经授权修改配置
Repudiation⚠️无合法身份痕迹
Information Disclosure查看/修改敏感配置
Denial of Service⚠️可滥用资源
Elevation of Privilege未授权执行管理员操作
该漏洞核心是 认证信任破坏,攻击者借助伪造身份标识绕过权限边界。

漏洞复现原理图示说明

攻击步骤时序图

sequenceDiagram
    participant A as 攻击者
    participant N as Nacos服务器
    participant AF as AuthFilter
    participant API as API处理器
    participant DB as 数据库
    
    A->>N: 1. 探测请求<br>GET /nacos/v1/auth/users
    N->>AF: 2. 请求进入过滤器
    AF->>A: 3. 返回403 Forbidden
    
    Note right of A: 攻击者识别到认证机制
    
    A->>N: 4. 伪造请求<br>添加User-Agent: Nacos-Server
    N->>AF: 5. 再次进入过滤器
    AF->>AF: 6. 检测UA头<br>发现"Nacos-Server"
    AF->>API: 7. 跳过认证<br>直接放行
    
    API->>DB: 8. 执行敏感操作
    DB->>API: 9. 返回操作结果
    API->>A: 10. 返回成功响应
    
    Note right of A: 攻击者获得未授权访问权限

正常访问流程与绕过流程对比如下:

Normal Client:

ClientAuthFilterValidate CredentialsBusiness Logic

Bypass Path:

AttackerAuthFilterSkipValidation (User-Agent Trusted) → Business Logic (Admin)


说明:AuthFilter 的预期功能是处理所有进入请求的身份验证,而绕过逻辑使特定 User-Agent 跳过了这一层检查,直接进入管理功能区域。

例如:未伪造 User-Agent 的请求:POST /nacos/v1/cs/configs?... → 403 Forbidden (Unknown user) 伪造:curl -X POST -A Nacos-Server "http://host:8848/nacos/v1/cs/configs?..." → true 说明认证被成功绕过,直接得到成功响应。

根本原因 在受影响版本中:

  • Nacos 存在 默认鉴权绕过问题
  • 某些管理 API 未进行权限校验
  • 可直接调用内部执行接口
  • 通过构造特定请求实现命令执行

实际漏洞链条 Step 1:未授权访问接口 攻击者直接访问:/nacos/v1/auth/users/nacos/v1/cs/ops/derby

Step 2:利用内部操作接口 PoC 脚本核心逻辑通常是:

  • 伪造请求
  • 注入执行命令参数
  • 触发 Java Runtime 执行

python CVE-2021-29442.py -t http://localhost:8848 -c "cat /etc/shadow 2>/dev/null" 本质是POST /nacos/v1/cs/ops/derby内部调用 Java 执行Runtime.getRuntime().exec(cmd)导致cat /etc/shadow被直接执行。

STRIDE 分析

威胁类型是否说明
Spoofing伪造 API 调用
Tampering可执行任意命令
Repudiation⚠️默认日志不足
Info Disclosure可读取敏感文件
DoS可执行高负载命令
Elevation若以 root 运行则完全沦陷

漏洞复现

Snipaste_2026-01-10_16-59-36.png

官方Poc,与Wiki相比,它是直接将*.jar文件进行密码哈希后添加到一个自动化脚本当中。我们运行与python CVE-2021-29442.py -t http://localhost:8848 -c "cat /etc/shadow 2>/dev/null" 类似的命令。

Snipaste_2026-01-10_16-58-22.png

Snipaste_2026-01-10_00-59-13.png

python CVE-2021-29442.py -t http://localhost:8848 -c "cat /etc/shadow 2>/dev/null" 
{"code":200,"message":null,"data":""}
{"code":200,"message":null,"data":[{"B":0,"A":"root:*:19901:0:99999:7:::daemon:*:19901:0:99999:7:::bin:*:19901:0:99999:7:::sys:*:19901:0:99999:7:::sync:*:19901:0:99999:7:::games:*:19901:0:99999:7:::man:*:19901:0:99999:7:::lp:*:19901:0:99999:7:::mail:*:19901:0:99999:7:::news:*:19901:0:99999:7:::uucp:*:19901:0:99999:7:::proxy:*:19901:0:99999:7:::www-data:*:19901:0:99999:7:::backup:*:19901:0:99999:7:::list:*:19901:0:99999:7:::irc:*:19901:0:99999:7:::gnats:*:19901:0:99999:7:::nobody:*:19901:0:99999:7:::_apt:*:19901:0:99999:7:::"}]}

接着,我们复现nacos/CVE-2021-29441。启动服务时,发现3306端口已经被Mysql80占用。

docker compose up -d
time="2026-01-10T17:23:59+08:00" level=warning msg="C:\\Users\\lucky\\vulhub\\nacos\\CVE-2021-29441\\docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion"
[+] Running 0/1
 - Container mysql  Starting                                                                                                                                                                             0.0s 
Error response from daemon: ports are not available: exposing port TCP 0.0.0.0:3306 -> 127.0.0.1:0: listen tcp 0.0.0.0:3306: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

于是我输入以下的命令进行排查,最后利用services.msc命令启动进程管理器,手动停止Mysql的服务。

Snipaste_2026-01-10_17-32-45.png 真服了,对于同样的9848端口怎么也排除不了,修改配置文件也不行。于是乎,一顿操作猛如虎,结果怀疑是梯子到期或机器码和ip被锁定。不说了,都是泪啊,有CVE-2021-29442就不错了。

修复建议

这里只涵盖了CVE-2021-29441的修复建议。

  1. 升级版本:立即升级至 Nacos 1.4.1+2.0.1+。这些版本默认关闭了空鉴权逻辑。
  2. 开启鉴权:在 application.properties 中确保 nacos.core.auth.enabled=true
  3. 修改默认密钥
    • 修改 nacos.core.auth.server.identity.key
    • 修改 nacos.core.auth.server.identity.value
    • 修改 nacos.core.auth.plugin.nacos.token.secret.key(这是防止 JWT 伪造的关键)。
  4. 网络隔离:生产环境的 Nacos 控制台不应直接暴露在公网,建议通过内网或 VPN 访问。

伪代码级修复示例

官方修复的主要思路是移除基于 User-Agent 的硬编码识别,转而使用可配置的 Identity Key 和 Value 进行节点校验。

漏洞代码逻辑(抽象):

public class AuthFilter implements Filter {
    public void doFilter(ServletRequest request, ...) {
        String userAgent = ((HttpServletRequest)request).getHeader("User-Agent");
        
        // 危险:硬编码校验,容易被外部伪造
        if ("Nacos-Server".equals(userAgent)) {
            chain.doFilter(request, response); // 直接跳过鉴权
            return;
        }
        
        checkFullAuthentication(request);
    }
}

修复方案逻辑(抽象):

public class AuthFilter implements Filter {
    public void doFilter(ServletRequest request, ...) {
        // 1. 从配置中读取受信任的 Key 和 Value
        String identityKey = env.getProperty("nacos.core.auth.server.identity.key");
        String identityValue = env.getProperty("nacos.core.auth.server.identity.value");
        
        // 2. 检查请求头中是否包含自定义的身份标识(而非通用的 User-Agent)
        String requestValue = ((HttpServletRequest)request).getHeader(identityKey);
        
        if (identityValue.equals(requestValue) && !identityValue.isEmpty()) {
            chain.doFilter(request, response); 
            return;
        }
        
        // 3. 否则进行严格的 Token/账号校验
        validateToken(request);
    }
}

更严格的修改策略

// 修复后的AuthFilter
public class FixedAuthFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, 
                         FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest request = (HttpServletRequest) req;
        String uri = request.getRequestURI();
        
        // 不再仅依赖User-Agent判断
        // 改为多重验证机制
        
        // 1. 检查是否为内部API调用(需要更严格的验证)
        boolean isInternalRequest = isInternalRequest(request);
        
        if (isInternalRequest) {
            // 2. 验证请求来源IP(白名单)
            String clientIp = request.getRemoteAddr();
            if (!isTrustedIp(clientIp)) {
                sendError(resp, "Unauthorized internal request");
                return;
            }
            
            // 3. 验证内部令牌(如果存在)
            String internalToken = request.getHeader("X-Nacos-Internal-Token");
            if (!validateInternalToken(internalToken)) {
                sendError(resp, "Invalid internal token");
                return;
            }
        }
        
        // 4. 执行正常认证流程
        if (!checkAuthentication(request)) {
            sendError(resp, "Authentication required");
            return;
        }
        
        chain.doFilter(req, resp);
    }
    
    private boolean isInternalRequest(HttpServletRequest request) {
        // 更严格的内部请求判断
        String userAgent = request.getHeader("User-Agent");
        return userAgent != null && userAgent.equals("Nacos-Server");
    }
    
    private boolean isTrustedIp(String ip) {
        // IP白名单验证
        return ip.startsWith("10.") || 
               ip.startsWith("192.168.") || 
               ip.equals("127.0.0.1");
    }
    
    private boolean validateInternalToken(String token) {
        // 内部令牌验证逻辑
        return token != null && token.equals(getExpectedToken());
    }
}

基于该漏洞的安全检测与防护规则

由于漏洞原理是绕过认证检查,可以设计如下检测与防护:

  1. WAF 策略规则(ModSecurity 示例) 规则:禁止未授权请求通过伪造 User-Agent 访问管理 API
SecRule REQUEST_HEADERS:User-Agent "Nacos-Server" \
    "id:100010,\
    phase:1,\
    block,\
    msg:'Potential Nacos Auth Bypass via UA Spoofing',\
    tag:'attack-injection',\
    severity:'CRITICAL',\
    chain"
    SecRule REQUEST_URI "@rx ^/nacos/v1/(auth|cs)/" \
        "t:none,\
        setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

说明:

  • 匹配严格的 User-Agent
  • 阻断此类访问请求
  • 结合访问路径策略进一步收敛:仅针对 /nacos/v1/cs/* 管理路径
  1. IDS / Suricata 示例规则
alert tcp $EXTERNAL_NET any -> $HOME_NET 8848 ( \
    msg:"NACOS Auth Bypass Attempt via UA Spoofing"; \
    flow:to_server,established; \
    content:"User-Agent"; content:"Nacos-Server"; \
    content:"POST"; content:"/nacos/v1/auth/users"; \
    classtype:web-application-attack; \
    sid:20211001; rev:1;)


  1. SIEM 关联检测(Splunk/ELK) 检测未经认证访问成功返回敏感端点:
index=web_logs "/nacos/v1/cs/" status=200
| stats count by src_ip, user_agent
| where user_agent="Nacos-Server"


本文参考:

[1].Nacos 历史漏洞复现 | X1ongSec www.qwesec.com/2025/06/nac…

[2].Vulnerability-Wiki/docs-base/docs/cloud/Nacos-未授权接口命令执行漏洞-CVE-2021-29442.md at master · Threekiii/Vulnerability-Wiki github.com/Threekiii/V…