commit 694ec0880553af9db8df9b0ea713be7755c1fd00 from: claudio date: Thu Feb 26 19:49:41 2026 UTC Error out on presence of Content-Length and Transfer-Encoding headers for GET, HEAD and other methods that should have no body. Ignoring the Content-Length header makes httpd vulnerable to HTTP request smuggling. A crafted GET request may embed an extra HTTP request which could bypass a proxy or WAF but then is handled by httpd. Remove the special case for TRACE and CONNECT in the Content-Length handling. Move those checks into the method switch at the end of the header parsing phase and by that also cover more methods including GET and HEAD. If either header is present simply abort the connection, nobody should send extra data along GET and HEAD requests. Add an an explicit HTTP_METHOD_TRACE case above the default case to indicated that we deliberately don't handle TRACE requests. This security vulnerability was found by Nicola Staller of SySS GmbH. With and OK rsadowski@ previous version also OK florian@ commit - 5e36945a5e19c646c571b6400ed1cb5a0871257f commit + 694ec0880553af9db8df9b0ea713be7755c1fd00 blob - afdb73f243f7eb2c842352a4ea6475931d9a2246 blob + 6e5fce04845d132173effad6e2394a580d27e17a --- server_http.c +++ server_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_http.c,v 1.158 2026/02/02 13:37:33 claudio Exp $ */ +/* $OpenBSD: server_http.c,v 1.159 2026/02/26 19:49:41 claudio Exp $ */ /* * Copyright (c) 2020 Matthias Pressfreund @@ -385,16 +385,6 @@ server_read_http(struct bufferevent *bev, void *arg) } else if (desc->http_method != HTTP_METHOD_NONE && strcasecmp("Content-Length", key) == 0) { - if (desc->http_method == HTTP_METHOD_TRACE || - desc->http_method == HTTP_METHOD_CONNECT) { - /* - * These method should not have a body - * and thus no Content-Length header. - */ - server_abort_http(clt, 400, "malformed"); - goto abort; - } - /* * Need to read data from the client after the * HTTP header. @@ -432,6 +422,11 @@ server_read_http(struct bufferevent *bev, void *arg) switch (desc->http_method) { case HTTP_METHOD_CONNECT: + /* No body allowed */ + if (clt->clt_toread > 0 || desc->http_chunked) { + server_abort_http(clt, 400, "malformed"); + return; + } /* Data stream */ clt->clt_toread = TOREAD_UNLIMITED; bev->readcb = server_read; @@ -441,6 +436,14 @@ server_read_http(struct bufferevent *bev, void *arg) /* WebDAV methods */ case HTTP_METHOD_COPY: case HTTP_METHOD_MOVE: + /* + * These method should not have a body and thus no + * Content-Length or Transfer-Encoding: chunked header. + */ + if (clt->clt_toread > 0 || desc->http_chunked) { + server_abort_http(clt, 400, "malformed"); + return; + } clt->clt_toread = 0; break; case HTTP_METHOD_DELETE: @@ -478,6 +481,7 @@ server_read_http(struct bufferevent *bev, void *arg) /* 7. of RFC 9112 Section 6.3 */ clt->clt_toread = 0; break; + case HTTP_METHOD_TRACE: default: server_abort_http(clt, 405, "method not allowed"); return;