Share
## https://sploitus.com/exploit?id=AEE4B3AA-4C98-5A59-B89E-B854736F36DA
# CVE-2026-23918 โ€” Apache mod_http2 Double Free

**Affected:** Apache HTTP Server 2.4.66 with `mod_http2` + Event MPM  
**Fixed in:** Apache 2.4.67 (mod_h2 v2.0.37)  
**CVSS 3.1:** 8.8 HIGH โ€” Unauthenticated Remote Code Execution possible  
**CWE:** CWE-415 (Double Free)  

---

## What's the vulnerability

`mod_http2` in Apache 2.4.66 has a double-free bug inside `h2_mplx.c:m_stream_cleanup()`. The issue happens when a client sends a `HEADERS` frame immediately followed by a `RST_STREAM` on the same stream. If the timing is right, the stream ends up pushed twice into the `m->spurge` purge array. When the mplx gets destroyed, the APR pool is freed twice, which corrupts the heap and causes a SIGABRT or SIGSEGV.

Apache patched this in mod_h2 v2.0.37 by introducing `add_for_purge()`, a simple deduplication check that prevents the same stream from being added twice.

```c
// Vulnerable (spurge, h2_stream *) = stream;  // can happen twice

// Fixed (v2.0.37+)
static int add_for_purge(h2_mplx *m, h2_stream *stream) {
    for (int i = 0; i spurge->nelts; ++i)
        if (APR_ARRAY_IDX(m->spurge, i, h2_stream*) == stream)
            return FALSE;
    APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream;
    return TRUE;
}
```

---

## How the PoC works

By default the script runs a 3-phase pipeline on the target:

| Phase | What it does |
|-------|-------------|
| **1 โ€” Recon** | Detects Apache version, HTTP/2 support via ALPN, MPM type |
| **2 โ€” Exploit** | Sends threaded HEADERS+RST_STREAM bursts, tries inline then staged mode |
| **3 โ€” RCE Assessment** | Measures crash consistency and scores the risk level |

The RCE score is computed from three signals that are detectable remotely. First, whether Apache 2.4.66 is running. Second, whether Event or Worker MPM is in use (mod_http2 refuses to start with Prefork so if HTTP/2 works, it's a threaded MPM). Third, how deterministic the crash is โ€” a crash on the first round means the heap corruption is controlled and reproducible, which is what you need for RCE.

---

## Installation

```bash
pip install hpack requests
```

---

## Usage

```bash
# Full PoC on a single target (default behavior)
python poc.py -t 192.168.1.100

# Increase pressure with more rounds, bigger bursts and more threads
python poc.py -t 192.168.1.100 -n 20 -b 500 -w 5

# Passive check only, nothing is sent to the target
python poc.py -t example.com --check-only

# Scan a whole list of targets
python poc.py -l sites.txt -o results.json

# Passive check on a list
python poc.py -l sites.txt --check-only

# Generate a Markdown report after the run
python poc.py -t target.com --report report.md
```

### Options

| Flag | Default | Description |
|------|---------|-------------|
| `-t` | โ€” | Single target (hostname or IP) |
| `-l` | โ€” | File with targets, one per line |
| `-p` | 443 | Port |
| `-n` | 10 | Number of exploit rounds |
| `-b` | 200 | HEADERS+RST pairs per round |
| `-w` | 3 | Parallel connections per round |
| `-d` | 0.1 | Delay between rounds in seconds |
| `-m` | inline | Attack mode: `inline` or `staged` |
| `--no-tls` | โ€” | Use h2c instead of TLS |
| `--check-only` | โ€” | Passive recon only, no exploit |
| `-o` | โ€” | Save results to a JSON file |
| `--report` | โ€” | Generate a Markdown report |
| `-v` | โ€” | Verbose output |

### Target file format

```
# one target per line, comments are ignored
192.168.1.100
example.com
example.com:8443
https://example.com
http://example.com:8080
```

---

## RCE risk levels

| Level | What it means |
|-------|--------------|
| **CRITICAL** | 2.4.66 confirmed, HTTP/2 active, Event MPM detected, crash is deterministic โ€” patch right now |
| **HIGH** | 2.4.66 confirmed, HTTP/2 active, threaded MPM in use |
| **MEDIUM** | 2.4.66 detected but HTTP/2 or crash not confirmed yet |
| **LOW** | Version doesn't match or no HTTP/2 detected |
| **NONE** | Already patched to 2.4.67+ or not affected |

---

## How to patch

The proper fix is upgrading Apache to 2.4.67 or later. If you can't upgrade right away, disabling HTTP/2 removes the attack surface entirely:

```apacheconf
# Before
Protocols h2 http/1.1

# After (disables HTTP/2)
Protocols http/1.1
```

---

## Disclaimer

This tool is meant for authorized security testing and research only. Make sure you have explicit written permission before running it against any target. The author takes no responsibility for misuse.