You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,13 +4,13 @@ HTTP/1.1 server compliance and security tester. Sends malformed, ambiguous, and
4
4
5
5
**Website:**[mda2av.github.io/Http11Probe](https://MDA2AV.github.io/Http11Probe/) — full documentation, test glossary with RFC citations, and live probe results across all tested servers.
6
6
7
-
## 116 Tests across 3 Categories
7
+
## 146 Tests across 3 Categories
8
8
9
9
| Category | Tests | What it covers |
10
10
|----------|------:|----------------|
11
-
|**Compliance**|47| RFC 9110/9112 protocol requirements — bare LF, obs-fold, missing Host, invalid versions, chunked encoding, upgrade handling, etc. |
12
-
|**Smuggling**|50| CL/TE ambiguity, duplicate Content-Length, pipeline desync, TE obfuscation, chunk extension abuse, bare LF in chunked framing |
Each test is scored against RFC normative language (MUST/SHOULD/MAY) and classified as **Pass**, **Fail**, or **Warn** (when the RFC permits both strict and lenient behavior).
A valid chunked POST where the chunk size is expressed using an uppercase hexadecimal digit: `A` (which equals 10 in decimal), followed by exactly 10 bytes of data.
18
+
19
+
```http
20
+
POST / HTTP/1.1\r\n
21
+
Host: localhost:8080\r\n
22
+
Transfer-Encoding: chunked\r\n
23
+
\r\n
24
+
A\r\n
25
+
helloworld\r\n
26
+
0\r\n
27
+
\r\n
28
+
```
29
+
30
+
The chunk size `A` is uppercase hex for 10. The chunk data `helloworld` is exactly 10 bytes.
31
+
32
+
## What the RFC says
33
+
34
+
> "chunk-size = 1*HEXDIG" -- RFC 9112 Section 7.1
35
+
36
+
`HEXDIG` is defined as `DIGIT / "A" / "B" / "C" / "D" / "E" / "F"` (case-insensitive per RFC 5234 ABNF conventions). Both `a` and `A` represent the decimal value 10. A compliant chunked parser must accept hex digits in any case.
37
+
38
+
## Why it matters
39
+
40
+
While most chunk sizes in practice are small decimal numbers (like `5` or `1a`), the grammar allows any combination of uppercase and lowercase hex digits. A parser that only handles lowercase hex, or only decimal digits, will fail on legitimate chunked bodies. This is a basic interoperability requirement for any HTTP/1.1 implementation.
41
+
42
+
## Sources
43
+
44
+
-[RFC 9112 §7.1 -- Chunked Transfer Coding](https://www.rfc-editor.org/rfc/rfc9112#section-7.1)
A valid chunked POST with a single 5-byte chunk, a zero terminator, and a trailer field (`X-Checksum: abc`) after the final chunk.
18
+
19
+
```http
20
+
POST / HTTP/1.1\r\n
21
+
Host: localhost:8080\r\n
22
+
Transfer-Encoding: chunked\r\n
23
+
\r\n
24
+
5\r\n
25
+
hello\r\n
26
+
0\r\n
27
+
X-Checksum: abc\r\n
28
+
\r\n
29
+
```
30
+
31
+
The trailer section appears between the zero-length terminating chunk and the final empty line.
32
+
33
+
## What the RFC says
34
+
35
+
> "A trailer section allows the sender to include additional fields at the end of a chunked message in order to supply metadata that might be dynamically generated while the content is sent." -- RFC 9112 Section 7.1.2
36
+
37
+
The chunked encoding grammar explicitly includes an optional trailer section:
Trailer fields are valid metadata that follow the zero-length terminating chunk. A compliant HTTP/1.1 server must be able to parse them, even if it chooses to discard them.
45
+
46
+
## Why it matters
47
+
48
+
Trailer fields are used in practice for checksums, signatures, and streaming metadata that cannot be known until the body has been fully generated. A server that rejects a valid chunked body just because it contains a trailer section has an incomplete chunked encoding parser. This can break interoperability with legitimate clients and proxies that use trailers.
A standard GET request with `Connection: close` indicating the client wants the server to close the connection after sending the response.
18
+
19
+
```http
20
+
GET / HTTP/1.1\r\n
21
+
Host: localhost:8080\r\n
22
+
Connection: close\r\n
23
+
\r\n
24
+
```
25
+
26
+
## What the RFC says
27
+
28
+
> "A server that receives a 'close' connection option MUST initiate a close of the connection after it sends the final response to the request in which the 'close' was received." -- RFC 9112 Section 9.3
29
+
30
+
The server must both respond successfully and close the TCP connection afterward. Responding with `2xx` but leaving the connection open violates this requirement.
31
+
32
+
## Why it matters
33
+
34
+
If a server ignores `Connection: close` and keeps the connection alive, a client may send a second request on what it believes is a new connection. In proxy environments, this can lead to response mismatch: the proxy believes the connection is closed and assigns it to a different client, who then receives the first client's response. Honoring `Connection: close` is essential for correct connection lifecycle management.
An HTTP/1.0 GET request without a `Connection: keep-alive` header.
18
+
19
+
```http
20
+
GET / HTTP/1.0\r\n
21
+
Host: localhost:8080\r\n
22
+
\r\n
23
+
```
24
+
25
+
## What the RFC says
26
+
27
+
HTTP/1.0 connections are not persistent by default. Unlike HTTP/1.1, where persistent connections are the default, an HTTP/1.0 client must explicitly request persistence via `Connection: keep-alive`.
28
+
29
+
> "If the received protocol is HTTP/1.0, the 'close' connection option is to be assumed." -- RFC 9112 Section 9.3
30
+
31
+
Without `Connection: keep-alive`, the server should treat the connection as non-persistent and close it after delivering the response.
32
+
33
+
**Pass:** Server responds `2xx` and closes the connection.
34
+
**Warn:** Server responds `2xx` but keeps the connection open (minor violation of SHOULD).
35
+
36
+
## Why it matters
37
+
38
+
If a server treats HTTP/1.0 connections as persistent by default, it may hold the connection open indefinitely waiting for another request that will never come, wasting resources. More critically, in proxy chains, a downstream server keeping an HTTP/1.0 connection alive when the proxy expects it to close can cause response desynchronization.
A request with a `Host` header present but with an empty value.
18
+
19
+
```http
20
+
GET / HTTP/1.1\r\n
21
+
Host: \r\n
22
+
\r\n
23
+
```
24
+
25
+
The `Host` header line exists, but its value is empty (nothing between the colon and CRLF).
26
+
27
+
## What the RFC says
28
+
29
+
> "A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field and to any request message that contains more than one Host header field line or a Host header field with an invalid field value." -- RFC 9112 Section 3.2
30
+
31
+
An empty Host value is invalid when the request-target is in origin-form. The host identification is effectively absent, making the server unable to determine which virtual host is being addressed.
32
+
33
+
## Why it matters
34
+
35
+
A Host header with an empty value is functionally equivalent to having no Host header at all. If a server accepts this, it may fall back to a default virtual host, potentially serving content from an unintended application. In multi-tenant environments, this can lead to information disclosure or incorrect routing.
No `Host` header is present, and the HTTP version is 1.0.
25
+
26
+
## What the RFC says
27
+
28
+
The `Host` header requirement was introduced in HTTP/1.1. HTTP/1.0 predates this requirement, so an HTTP/1.0 request without a `Host` header is not technically a protocol violation:
29
+
30
+
> "A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field..." -- RFC 9112 Section 3.2
31
+
32
+
Note the requirement explicitly says "HTTP/1.1 request message." For HTTP/1.0, the server may choose to accept the request (routing to a default virtual host) or reject it.
33
+
34
+
**Pass:** Server rejects with `400` (strict -- good security practice).
35
+
**Warn:** Server accepts with `200` (valid -- HTTP/1.0 did not require Host).
36
+
37
+
## Why it matters
38
+
39
+
In a virtual hosting environment, a request without a `Host` header gives the server no indication of which site is being targeted. Accepting such requests means the server must fall back to a default host, which could serve unintended content. Rejecting HTTP/1.0 requests without `Host` is the safer approach, especially since legitimate modern clients always send a `Host` header regardless of HTTP version.
description: "CHUNK-EXTENSION-LONG test documentation"
2
+
title: "CHUNK-EXT-64K"
3
+
description: "CHUNK-EXT-64K test documentation"
4
4
weight: 18
5
5
---
6
6
7
7
|||
8
8
|---|---|
9
-
|**Test ID**|`MAL-CHUNK-EXTENSION-LONG`|
9
+
|**Test ID**|`MAL-CHUNK-EXT-64K`|
10
10
|**Category**| Malformed Input |
11
11
|**Expected**|`400`/`431` or close |
12
12
13
13
## What it sends
14
14
15
-
A chunked request with a chunk extension containing 100KB of data.
15
+
A chunked request with a chunk extension containing 64KB (65,536 bytes) of data.
16
16
17
17
```http
18
18
POST / HTTP/1.1\r\n
19
19
Host: localhost:8080\r\n
20
20
Transfer-Encoding: chunked\r\n
21
21
\r\n
22
-
5;ext=AAAA...{100,000 × 'A'}...\r\n
22
+
5;ext=aaaa...{65,536 x 'a'}...\r\n
23
23
hello\r\n
24
24
0\r\n
25
25
\r\n
26
26
```
27
27
28
-
The chunk extension value is 100,000 bytes of `A` characters.
28
+
The chunk extension value is 65,536 bytes of `a` characters.
29
29
30
30
31
31
## Why it matters
32
32
33
-
While chunk extensions are syntactically valid per RFC 9112 Section 7.1.1, a 100KB extension is pathological. A robust server should reject unreasonably large chunk extensions to prevent resource exhaustion and denial of service.
33
+
While chunk extensions are syntactically valid per RFC 9112 Section 7.1.1, a 64KB extension is pathological. A robust server should reject unreasonably large chunk extensions to prevent resource exhaustion and denial of service. CVE-2023-39326 demonstrated that Go's `net/http` library could be exploited via large chunk extensions to cause excessive memory consumption and DoS.
A POST request declaring a ~1GB body via Content-Length but sending no body data at all.
17
+
18
+
```http
19
+
POST / HTTP/1.1\r\n
20
+
Host: localhost:8080\r\n
21
+
Content-Length: 999999999\r\n
22
+
\r\n
23
+
```
24
+
25
+
No body follows the empty line. The connection remains open.
26
+
27
+
## Why it matters
28
+
29
+
Tests whether the server pre-allocates memory for the declared body size or waits for data to arrive. A server that allocates 1GB upfront from a Content-Length header is vulnerable to memory exhaustion DoS -- an attacker can send many such requests cheaply to exhaust server memory. The correct behavior is to either stream the body incrementally, reject absurdly large Content-Length values, or timeout waiting for the body data that never arrives.
0 commit comments