Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect bad framing #682

Open
olix0r opened this issue Sep 19, 2016 · 5 comments
Open

Detect bad framing #682

olix0r opened this issue Sep 19, 2016 · 5 comments

Comments

@olix0r
Copy link
Member

olix0r commented Sep 19, 2016

From https://www.mnot.net/blog/2011/07/11/what_proxies_must_do

Proxies also need to be on the lookout for Content-Length headers that are duplicates, as well as ones that conflict with the use of Transfer-Encoding, and either reject the message or remove the bad headers.

This is because there are entire classes of attacks that exploit the differences between how implementations frame messages.

For example, this response:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 45
Content-Length: 20

has an ambiguous length. If a proxy treats it differently than a client, an attacker can inject a response. Likewise, this one:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 200
Transfer-Encoding: chunked

has both a Content-Length and chunked encoding. The chunked encoding has precedence, and the Content-Length has to be removed before forwarding the message.

See the spec for how to do it well.

@olix0r
Copy link
Member Author

olix0r commented Sep 19, 2016

I suspect that finagle does most of this for us, but we should verify in e2e tests

@hawkw hawkw self-assigned this Jun 30, 2017
@hawkw
Copy link
Member

hawkw commented Jul 3, 2017

I'm working on a tool to automate this, and so far, I've found at least one case we're not handling correctly.

According to the spec:

If a message is received without Transfer-Encoding and with
either multiple Content-Length header fields having differing
field-values or a single Content-Length header field having an
invalid value, then the message framing is invalid and MUST be
treated as an error to prevent request or response smuggling.
...
If this is a response message received by a proxy, the proxy MUST
discard the received response, send a 502 (Bad Gateway) status
code as its downstream response, and then close the connection.

We are, as you might have guessed, Not Doing This.

Testing with flossy, where the upstream server sends first bad response message in the blog post @olix0r quoted above (with multiple Content-Length headers), linkerd happily forwards the bad response, multiple headers intact.

(N.B. for potential users of flossy – it's currently a minimum working proof-of-concept. you probably don't want to use this yet)

@hawkw
Copy link
Member

hawkw commented Jul 3, 2017

I did a manual telnet session to confirm (I don't entirely trust flossy yet; there's probably several lurking bugs in there):

GET https://127.0.0.1:7777/test1 HTTP/1.1

HTTP/1.1 200 OK
Server: Example
Content-Length: 31
Date: Mon, 03 Jul 2017 15:15:07
Content-Length: 45
Content-Length: 20
l5d-success-class: 1.0
Via: 1.1 linkerd

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

So yeah. This is real.

@hawkw
Copy link
Member

hawkw commented Jul 6, 2017

Additional testing with the latest flossy reveals that we're also mishandling the case of a request with multiple Content-Length headers – I'll open an issue for that too.

@hawkw
Copy link
Member

hawkw commented Jul 6, 2017

Still need to add similar tests in flossy for chunked encodings (BuoyantIO/flossy#2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants