NUL-IN-URL
| Test ID | MAL-NUL-IN-URL |
| Category | Malformed Input |
| Expected | 400 or close |
What it sends
A request with a NUL byte (\x00) embedded in the URL.
GET /\x00test HTTP/1.1\r\n
Host: localhost:8080\r\n
\r\n
The URL contains a NUL byte (\x00) between / and test.
What the RFC says
The request-target in an HTTP/1.1 request must conform to the URI grammar from RFC 3986. The pchar rule defines valid path characters:
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"— RFC 3986 Section 3.3
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"— RFC 3986 Section 2.3
A raw NUL byte (0x00) is not included in any of these productions, making it an invalid character in a URI path.
"When a server listening only for HTTP request messages...receives a sequence of octets that does not match the HTTP-message grammar...the server SHOULD respond with a 400 (Bad Request) response and close the connection." — RFC 9112 Section 2.2
Why it matters
NUL bytes terminate strings in C/C++. A NUL in the URL could cause path truncation in backend systems, allowing path traversal or access to unintended resources.
Deep Analysis
Relevant ABNF
request-line = method SP request-target SP HTTP-version
origin-form = absolute-path [ "?" query ]
absolute-path = 1*( "/" segment )
segment = *pchar
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
RFC Evidence
"A URI is composed from a limited set of characters consisting of digits, letters, and a few graphic symbols." -- RFC 3986 Section 2
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"-- RFC 3986 Section 3.3
"When a server listening only for HTTP request messages...receives a sequence of octets that does not match the HTTP-message grammar aside from the robustness exceptions listed above, the server SHOULD respond with a 400 (Bad Request) response and close the connection." -- RFC 9112 Section 2.2
Chain of Reasoning
-
NUL (
0x00) matches no URI production. Walking through every alternative inpchar:unreservedcovers onlyALPHA(%x41-5A,%x61-7A),DIGIT(%x30-39), and four specific symbols;pct-encodedrequires a leading%;sub-delimslists specific ASCII punctuation;:is%x3A;@is%x40. The byte0x00is below the lowest value in any of these sets. -
NUL is not even a valid request-line octet. The
request-linegrammar requiresmethod SP request-target SP HTTP-version. TheSPcharacter is%x20. Themethodis atoken(requirestchar, minimum%x21). There is no production in the HTTP/1.1 grammar that accommodates%x00anywhere in the request-line. -
The grammar violation triggers the rejection rule. Since the
request-targetcontains an octet that does not match the URI grammar, the entire request-line fails to matchHTTP-message. RFC 9112 Section 2.2 instructs the server to respond with 400 and close. -
C-string truncation is the primary exploit vector. In C and C++, strings are NUL-terminated. A NUL byte at position 1 in
/\x00testwould causestrlen()to return 1, making the path appear as just/. This can bypass path-based access controls, allow directory listing where only specific files should be served, or truncate filenames to access unintended resources. -
No robustness exception applies. The only robustness exception in RFC 9112 Section 2.2 is ignoring empty CRLF lines before the request-line. NUL bytes receive no such exception.
Sources
- RFC 3986 Section 3.3 — URI path and pchar grammar
- RFC 9112 Section 2.2 — rejection of invalid messages