Posted on 02 Apr 2018.
During a vulnerability research spree, I came across this GitHub issue titled Potential HTTP Response Splitting Vulnerability, belonging to the gunicorn project. The title says “potential”, but the vulnerability was present and got fixed in commit 6c3d8.
In an effort to spread this information to anyone considering using this version of gunicorn, I’ll fill in a DWF report hoping this issue gets a CVE ID and that knowledge of its existance becomes more widespread.
An HTTP header splitting vulnerability is caused by not sanitizing strings containing characters with special meaning in HTTP (such as
LF) in data that will later be used to generate HTTP headers.
We can test this vulnerability by creating a Python2 virtual environment with gunicorn 19.4.5 installed:
user@pc:~$ virtualenv venv user@pc:~$ source venv/bin/activate (venv) user@pc:~$ pip install gunicorn==19.4.5
The following code (
myapp.py) will define both
def app(environ, start_response): data = b"Hello, World!\n" start_response("200 OK", [ ("Content-Type", "text/plain"), ("Foo", "Foo\r\nBar: Bar"), ("Content-Length", str(len(data))) ]) return iter([data])
We can run this by executing
gunicorn -w 4 myapp:app and going to
http://127.0.0.1:8000. Here’s the resulting HTTP response:
user@pc:~$ curl -i http://127.0.0.1:8000/ HTTP/1.1 200 OK Server: gunicorn/19.4.5 Connection: close Content-Type: text/plain Foo: Foo Bar: Bar Content-Length: 14 Hello, World!
If we attempt to do this in gunicorn 19.5.0+, this will be the resulting HTTP response:
user@pc:~$ curl -i http://127.0.0.1:8000/ HTTP/1.1 400 Bad Request Connection: close Content-Type: text/html Content-Length: 163 <html> <head> <title>Bad Request</title> </head> <body> <h1><p>Bad Request</p></h1> Invalid HTTP Header: "'Foo\\r\\nBar: Bar'" </body> </html>
This behavior is expected, thanks to commit 6c3d8.