Forums » Development »
[Solved] Lighttpd allows extra bytes between CR and LF after chunk-size
Added by kenballus 6 months ago
When Lighttpd receives an HTTP/1.1 request with extra bytes between the CR and the LF following a chunk-size (except in the last chunk), it ignores the extra bytes. This is kind of weird, because Lighttpd doesn't allow extra bytes between CR and LF in other contexts.
For example, Lighttpd accepts the following request, and interprets its message body as "Z":
POST / HTTP/1.1\r\n Host: whatever\r\n Transfer-Encoding: chunked\r\n \r\n 1\rAnything that you put here gets ignored, except NUL. This ignored data is terminated with LF.\n Z\r\n 0\r\n \r\n
In the final chunk, there's a similar strange behavior, but it works a little differently:
POST / HTTP/1.1\r\n Host: whatever\r\n Transfer-Encoding: chunked\r\n \r\n 1\r\n Z\r\n 0\rAnything that you put here gets ignored, except NUL. This ignored data is terminated with CRLF.\r\n \r\n
Replies (2)
RE: Lighttpd allows extra bytes between CR and LF after chunk-size - Added by gstrauss 6 months ago
lighttpd is parsing chunked headers looking for \n
and should more strictly enforce that HTTP/1.1 chunked header line ends with \r\n
Preliminary patch (not yet tested)
--- a/src/h1.c +++ b/src/h1.c @@ -625,7 +625,7 @@ h1_chunked (request_st * const r, chunkqueue * const cq, chunkqueue * const dst_ return http_response_reqbody_read_error(r, 400); } while (*s == ' ' || *s == '\t') ++s; - if (*s != '\r' && *s != ';') { + if (p[-1] != '\r' || (p-1 != (char *)s && *s != ';')) { log_error(r->conf.errh, __FILE__, __LINE__, "chunked header invalid chars -> 400"); /* 400 Bad Request */
lighttpd currently recognizes trailers on HTTP/1.1 chunked requests, but ignores and does not validate trailers, so anything between final chunk (0\r\n
) and \r\n\r\n
is read and discarded.
RE: Lighttpd allows extra bytes between CR and LF after chunk-size - Added by gstrauss 6 months ago
https://lists.w3.org/Archives/Public/ietf-http-wg/2023JulSep/0160.html recommends that parsing HTTP/1.1 chunked header should require CRLF and should not permit bare LF.
I have committed a change to strictly require CRLF on HTTP/1.1 chunked header, both in HTTP/1.1 requests and in HTTP/1.1 responses received from lighttpd backends.
Note: bare CR before the CRLF on the chunked header is not detected, since I deem further scanning and parsing chunked-ext for bare CR to be too pedantic; low value and low risk.