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

Add a ZeroLengthHeaderError raised if header name is 0-length #169

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

pgjones
Copy link
Member

@pgjones pgjones commented Aug 26, 2019

This is to mitigate CVE-2019-9516, 0-Length Headers Leak. It will
allow hpack users, such as hyper-h2, to close connections if this
happens on the basis that the client is likely attempting a DoS
attack.

(I'm happy to help maintain hpack if desired, I would release 3.1.0 with this fix at a minimum).

Copy link
Contributor

@alexwlchan alexwlchan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CVE talks about 0-length header names and values, but this patch only seems to check for 0-length names. Is that intentional?

If so, maybe rename to ZeroLengthHeaderNameError for extra specificity?

HISTORY.rst Outdated Show resolved Hide resolved
HISTORY.rst Outdated Show resolved Hide resolved
@Lukasa
Copy link
Member

Lukasa commented Aug 26, 2019

This patch isn’t actually necessary. If you try to mount the attack you’ll find it doesn’t work, because we don’t treat a name-value pair of “””,”” as having length 0 but instead as having length 32. We don’t need an extra defense here.

@pgjones
Copy link
Member Author

pgjones commented Aug 27, 2019

@Lukasa I see, this line is the key part then?

Whilst not necessary, is it still useful? Sending zero length headers isn't a legitimate thing for a client to do, with this hyper-h2 can respond like this if a client sends them.

@alexwlchan the CVE talks of both, but I've not seen an implementation that checks the value length. Maybe Lukasa can say more? My guess would be that it isn't infeasible to have a header field name without a value.

@Lukasa
Copy link
Member

Lukasa commented Aug 27, 2019

I wrote a patch to swift-nio-http2 that rejects zero length header field names on the grounds that RFC7230 forbids them in HTTP/1. It’s a reasonable patch; just not a security one. I have seen header fields without values in the wild before and expect to see them again.

This that indicates that an invalid header has been received. This
places the HPACK decoder into a broken state: it must not be used
after this exception is thrown.
@pgjones
Copy link
Member Author

pgjones commented Aug 27, 2019

I've reworded it to remove the security references and to rename as ZeroLengthHeaderNameError. With #170 I think the build will pass.

@alexwlchan
Copy link
Contributor

alexwlchan commented Aug 28, 2019

Current patch looks good.

Thinking some more, there's nothing to block encoding zero-length headers. This means we can encode headers that we'd promptly refuse to decode:

from hpack.hpack import Decoder, Encoder

e = Encoder()

encoded_bytes = e.encode({"": "nope"})
print(encoded_bytes)

d = Decoder()
decoded_bytes = d.decode(encoded_bytes)

How do we feel about that?

I can imagine there are use cases (e.g. mitmproxy) where being able to send zero-length header names is a useful feature – for example, to test that a server handles this attack correctly! But maybe it should be an error in regular usage, and you have to opt into allowing it?

@pgjones
Copy link
Member Author

pgjones commented Aug 29, 2019

Sounds sensible to me, could we split it into a second PR though (I think we'd need to discuss how to make it optional).

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

Successfully merging this pull request may close these issues.

3 participants