# CVE-2026-47291: Remote Code Execution in the Windows HTTP.sys

16-bit capacity overflow in HTTP.sys buffer reference array during HTTP/1.x header parsing over TLS yields kernel pool heap overflow, enabling DoS or kernel RCE.

- Payout: Research
- Severity: critical
- Program: Microsoft
- Write-up by: TrendAI Research Team
- Disclosed: 2026-07-10
- CVE: CVE-2026-47291
- Write-up quality: 8/10
- Original: https://www.thezdi.com/blog/2026/7/9/cve-2026-47291-remote-code-execution-in-the-windows-httpsys
- Library page: https://bugbountylibrary.com/r/blog%3Athezdi-com-blog-2026-7-9-cve-2026-47291-remote-code-execution-in-the-windows-httpsys
- Tags: area:cloud domain:infra impact:dos impact:rce kind:research platform:research sev:critical tech:windows technique:chained technique:source-review vuln:dos vuln:memory-corruption vuln:rce

**Target:** HTTP.sys kernel driver (IIS HTTP protocol stack) over TLS port 443
**Root cause:** The buffer reference array growth routine increments a 16-bit capacity field by 5 without overflow check; after 13,107 growths capacity wraps 0xFFFB+5 to 0x0000, so the next growth allocates only 0x28 bytes while memmove copies count*8 (~524KB) bytes.
**Steps:**
1. Configure target MaxRequestBytes >= 262144 (default 16384 insufficient).
2. Open TLS connection to port 443; send HTTP/1.x request where each header line is encapsulated in its own TLS application data record (each line CRLF-terminated, ~4 bytes min).
3. Each record is decrypted independently by SChannel and delivered via UlHttpBufferReceiveEvent() as a separate buffer, adding one buffer reference per record (1:1 correspondence).
4. Send ~65,536 header lines/records (~262KB total, ~11 min at 10ms/record) to drive capacity through 13,107 growth events to 0xFFFB, then wrap to 0x0000.
5. Next buffer reference addition triggers growth: allocation 0x28 + 0*8 = 40 bytes, memmove copies count*8 (~524,256 bytes) -> kernel pool heap overflow.
**How found:** Researchers noted that over TLS each record is decrypted independently and delivered as a separate buffer via UlHttpBufferReceiveEvent(), unlike plaintext where TCP coalesces segments; combined with the observation that a header line fully contained in one record avoids the partial-parse merge path (UlpAdjustBuffers non-merge), creating 1:1 record-to-buffer-reference mapping. Code review of the inline buffer reference growth routine revealed the unchecked 16-bit capacity increment.
**Exploitation:** Remote unauthenticated attacker sends crafted HTTP/1.x request over TLS with one header line per TLS record to accumulate 65,536 buffer references, wrapping the 16-bit capacity and causing a >500KB kernel pool heap overflow; results in system termination via kernel memory access exception, and under specific memory layout conditions arbitrary kernel-mode code execution.
**Insight:** TLS record boundaries create per-record buffer deliveries that bypass the coalescing/merge paths used for plaintext, so parser state counters (array growth, reference counts) can be driven far faster than on plaintext; audit 16-bit capacity/count fields in kernel parsers for wrap-around and check allocation-size vs memmove-length mismatches after wrap.

