Blog
CVE-2026-47291: Remote Code Execution in the Windows HTTP.sys
In this excerpt of a TrendAI Research Services vulnerability report, Yazhi Wang and Jonathan Lein of the TrendAI Research team detail a recently patched remote code execution bug in the Windows HTTP protocol stack. Successful exploitation of this vulnerability can result in a denial-of-service condition, or, in the worst case, code execution with kernel privileges. The following is a portion of their write-up covering CVE-2026-47291, with a few minimal modifications.
A remote code execution vulnerability exists in the HTTP Protocol Stack for Microsoft Internet Information Services implemented in HTTP.sys. The vulnerability is due to invalid validating incoming HTTP requests.
A remote, unauthenticated attacker can exploit this vulnerability by sending crafted HTTP packets to the target system. Successful exploitation of this vulnerability can result in a denial-of-service condition, or, in the worst case, code execution with kernel privileges.
The Vulnerability
HTTP.sys is the kernel-mode HTTP protocol driver in Microsoft Windows. It provides HTTP request parsing, response caching, and SSL/TLS termination for Internet Information Services (IIS) and other applications that register URL prefixes. The driver listens on configured TCP ports (commonly 80 for HTTP and 443 for HTTPS) and processes inbound HTTP/1.x and HTTP/2 requests at the kernel level.
When operating over HTTPS, HTTP.sys delegates TLS processing to the Windows Secure Channel (SChannel) provider. Inbound TCP data is decrypted on a per-record basis: each TLS record constitutes an independent unit of encryption and is decrypted separately by SChannel before being delivered to HTTP.sys as a distinct plaintext buffer. A single TLS 1.3 application data record has the following structure:
The decrypted payload of each TLS record is delivered independently to the HTTP parser via
UlHttpBufferReceiveEvent(), regardless of how many TLS records the underlying TCP connection coalesces into a single TCP segment. This behavior is distinct from plaintext HTTP connections, where the Windows TCP stack coalesces multiple segments into a single receive indication before the data reaches HTTP.sys.
The HTTP parser maintains a per-request state object that includes a dynamically grown buffer reference array. The capacity field stores the current number of allocated slots in the buffer reference array. The count field stores the number of slots currently in use. The ref_array_ptr field points to the dynamically allocated array of 8-byte buffer reference entries.
An integer overflow vulnerability exists in HTTP.sys. The vulnerability is due to insufficient bounds checking when growing a buffer reference array during HTTP/1.x header parsing. When HTTP.sys receives data for an HTTP/1.x request, it allocates a UL_REQUEST_BUFFER structure for each receive indication and tracks these buffers in the per-request reference array described above. The count field records the number of active buffer references, and the capacity field records the total number of allocated slots.
As the HTTP parser (UlpParseNextRequest()) processes header lines, it calls an inline buffer reference routine each time a new receive buffer is consumed. When count reaches capacity, the routine grows the array by reallocating it with five additional slots. The new allocation size is computed as 0x28 + capacity * 8, the contents of the existing array are copied via memmove using count * 8 as the copy length, and capacity is incremented by 5 as a 16-bit unsigned integer addition. No overflow check is performed on this addition.
After 13,107 growth events, capacity reaches 0xFFFB. The next growth adds 5, producing 0x10000, which truncates to 0x0000 in the 16-bit field. On the subsequent buffer reference addition, count (which is now 65,536 or greater) exceeds the zero capacity, triggering another growth. The allocation size computation 0x28 + 0 * 8 produces a 40-byte allocation, but the memmove copies count * 8 bytes (approximately 524,256 bytes) from the old buffer into the 40-byte allocation. This results in a kernel pool heap buffer overflow of over 500 kilobytes.
Each buffer reference corresponds to one receive buffer delivered to the HTTP parser. For plaintext HTTP connections, the Windows TCP stack coalesces received segments into large indications, and UlpMergeBuffers() further combines buffers within HTTP.sys. Over TLS connections, each TLS record is decrypted independently by SChannel and delivered as a separate buffer through UlHttpBufferReceiveEvent() into UlpCopyIndicatedData(). If each TLS record contains exactly one complete header line (terminated by CRLF), the HTTP parser fully consumes the buffer without setting the partial-parse flag, causing UlpAdjustBuffers() to advance to the next buffer via its non-merge path. This creates a 1:1 correspondence between TLS records sent and buffer references accumulated.
To trigger the overflow, an attacker crafts an HTTP request in which each header line is encapsulated in a separate TLS application data record. Given a minimum header line size of approximately 4 bytes and a required count of 65,536 buffer references, the total request size comes to roughly 262,144 bytes. The MaxRequestBytes registry value (at HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters) must be configured to a value of at least 262,144 bytes for the server to accept a request of this size. The default value of 16,384 bytes limits the request to approximately 4000 header lines, which is insufficient to trigger the overflow. As a mitigation, keeping MaxRequestBytes at or below 65,535 bytes represents the most conservative configuration to prevent this attack.
A remote unauthenticated attacker could exploit this vulnerability by sending a specially crafted HTTP/1.x request over a TLS connection to an affected server. Successful exploitation results in unexpected system termination due to a memory access exception in the context of the kernel. Under specific memory layout conditions, exploitation could result in arbitrary code execution in the context of the kernel.
Notes:
• The vulnerability is only reachable through HTTP/1.x header parsing over TLS connections. HTTP/2 and HTTP/3 use different parser paths that do not interact with the buffer reference array.
• Body data parsing (Content-Length or chunked transfer encoding) does not add entries to the buffer reference array. Only header parsing triggers buffer reference growth.
• At a sending rate of 10 milliseconds per TLS record, the overflow requires approximately 11 minutes to trigger.
Source Code Walkthrough
The following code snippet was taken from HTTP.sys version 10.0.26100.7705. Comments added by TrendAI Research have been highlighted.
In UlpParseNextRequest():
Detection Guidance
To detect an attack exploiting this vulnerability, the detection device must monitor and parse traffic on the TCP port 443.
The traffic on the affected port(s) is TLS-encrypted. The detection device must be able to decrypt the TLS traffic before applying the following detection method. The detection device should monitor for HTTPS connections.
An HTTP/1.x request [1] consists of a request line followed by zero or more header field lines, each terminated by CRLF. The following grammar defines the relevant structure:
Decrypted traffic inspection:
After decrypting the TLS session, the detection device must parse the HTTP/1.x request headers. The detection device must count the number of distinct header field lines present in a single HTTP request. If the number of header field lines in a single request exceeds 1,000, the traffic should be considered suspicious; an attack exploiting this vulnerability is likely underway.
Encrypted traffic heuristics:
Where decryption is not available, the detection device should inspect the pattern of TLS application data records within the encrypted session. If each TLS application data record contains a single short payload and the total number of such records on a single connection exceeds 1,000, the traffic should be considered suspicious; an attack exploiting this vulnerability is likely underway.
Notes:
• The preferred detection method (header line count) requires the ability to decrypt TLS traffic, for example through TLS inspection, a decrypting proxy, or possession of the server's private key. This method directly observes the attack indicator and produces low false-positive and false-negative rates.
• The TLS record heuristic operates on encrypted traffic and does not require decryption. This method is more prone to false positives (legitimate applications that send many small TLS records, such as interactive streaming sessions, may trigger the heuristic) and to false negatives (the threshold is based on observable record sizes rather than the actual header count that determines exploitability). Where possible, decrypted traffic inspection should be preferred.
• The attack requires approximately 11 minutes of sustained connection to accumulate sufficient header lines. Connection duration monitoring may serve as a supplementary detection heuristic.
Conclusion
This vulnerability was patched by Microsoft in the June 2026 release cycle. They note several mitigations that include editing the registry to ensure unpatched systems are not vulnerable to exploitation. However, the best method to ensure this bug has been fully remediated is to test and deploy the vendor-supplied patch.
Special thanks to Yazhi Wang and Jonathan Lein of the TrendAI Research team for providing such a thorough analysis of this vulnerability. For an overview of TrendAI Research services, please visit https://go.trendmicro.com/tis/vulnerabilities.html.
The threat research team will be back with other great vulnerability analysis reports in the future. Until then, follow the team on Twitter, Mastodon, LinkedIn, or Bluesky for the latest in exploit techniques and security patches.