Project

General

Profile

[Solved] Lighttpd allows extra bytes between CR and LF after chunk-size

Added by kenballus 2 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 2 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 2 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.

    (1-2/2)