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
Version Negotiation DoS #522
Comments
An attacker would also have to guess the right port number, which should be close to 2 bytes of entropy in itself. |
Yeah, good point. But OSes are bad at handing out port numbers randomly -- I could be wrong, but I believe OSes hand these out sequentially to sockets. There may be far fewer than 2 bytes of entropy there. |
I said this over here, but I'll add it here for the benefit of this thread.
But I don't think that addresses the issue here. The issue here is that a client might want to validate a Version Negotiation packet. I separately opened #523 on that point, but this seems like it is asking the question about whether we have enough entropy to ensure that the Version Negotiation packet is OK. BTW, it's only 31-bits of entropy. Port number might be close to zero entropy, though in practice it's a fair bit better than that (maybe as much as 14 bits) and we might assume that the IP address is known, so zero entropy. If the benchmark is TCP, then we're 1 bit worse off. On the other hand, if the benchmark is DNS, things don't look too bad. Modern operating systems generate ephemeral addresses randomly. But it's usually from a small-ish slice of ports. Test that if you like:
|
... which goes back to my request to linking client chosen id to the server chosen id - in this case it would reduce attacks to those on path. |
Oh, so that I don't forget, we only use 31-bits because of the need to increment this number. If we randomize for every Client Initial packet, which seems perfectly doable now, then we can use the entire 32-bit space. That's all assuming that 32 is enough but 31 isn't... |
I just tested Windows 10 and it doesn't randomize the source port for ephemeral UDP. So no entropy there :( Back down to 31. |
This seems like a more generic issue in that it's possible to create a DOS attack essentially by sending any packet that appears to be from the server to the client that passes the QUIC packet checks but is bogus at an upper layer. For instance, one could send an SH that had a cipher suite Implicitly, this issue assumes that we want (or will live with)
It seems like it would be easiest to address this problem generically rather than Specifically: This will prevent injection attacks by any attacker who hasn't seen the client initial packet, this fixing both this issue and others. |
This almost makes sense to me except
|
I don't understand this. The HMAC is just replacing FNV-1a, so we'll pick an algorithm and stick with it.
What you gain is having something that's generic rather than something that requires specific intervention and analysis for each case. |
Yes, exactly - if 22 years from now, HMAC-SHA256 is trivially broken, you cannot replace it. FNV-1a does not attempt to be cryptographically strong, so it cannot break in the same way, but offer fewer guarantees in return. Note that I am not against using HMAC because it is a stronger defence againts obnoxious middleware, and since unencrypted payload is not bottleneck, there isn't much gain in choosing a cheaper solution. However, FNV-1a is simpler to specify as universally true which is probably why it was chosen.
Well, yes I do not disagree, I am just pointing out the the generic solution could also be just returning the initial Connection ID because the HMAC in this setup provides not stronger guarantees as far as I can tell. The only guarantee it provides is that that payload has not been tampered with, but that is for the handshake to decide, and the handshake goes to great lengths to support extensible cryptography (for better or worse). Alas, I wouldn't mind a much simpler QUIC version that just decided on CURVE25519 and be done with it, then change version if needed. And this is indeed possible to do. But for a generic version 1 of QUIC, you need to consider all this crypto replacability, I'm afraid. But, even before you wrote this, I was also thinking why not use a HMAC instead of FNV-1a, so I largely follow what you say. |
On Sat, May 13, 2017 at 12:30 PM, MikkelFJ ***@***.***> wrote:
the HMAC cannot trivially be version dependent then.
I don't understand this. The HMAC is just replacing FNV-1a, so we'll pick
an algorithm and stick with it.
Yes, exactly - if 22 years from now, HMAC-SHA256 is trivially broken, you
cannot replace it. FNV-1a does not attempt to be cryptographically strong,
so it cannot break in the same way, but offer fewer guarantees in return.
Note that I am not against using HMAC because it is a stronger defence
againts obnoxious middleware, and since unencrypted payload is not
bottleneck, there isn't much gain in choosing a cheaper solution. However,
FNV-1a is simpler to specify as universally true which is probably why it
was chosen.
Well, we chose FNV-1a when we weren't attempting to have something keyed.
WRT to the question of "trivially broken", I suppose that that's possible,
yes,
but then we'll basically be back to the situation we are in now. And you
would
need a very strong attack, one in which you had the ability to forge a MAC
with an unknown key and where you didn't get any known plaintext/ciphertext
pairs. To the best of my knowledge, we're nowhere near this with HMAC,
even with MD5.
It's always risky to analyze on the fly, but it seems like in order to have
this,
you would need to find some set of inputs to the compression function
which would spit out the same output with high probability no matter what
the current state of the compression function is.
However, if this is really something people are worried about then the
trivial
solution is to have an "integrity check" with consists of
conn_ID || FNV-1a(conn_id || packet)
This guarantees that no possible attack on the integrity function can result
in the attacker generating a packet which will be acceptable without knowing
the conn_id.
the HMAC key is public, so you don't gain much compared to returning the
initial connection id as I suggested earlier.
What you gain is having something that's generic rather than something
that requires specific intervention and analysis for each case.
Well, yes I do not disagree, I am just pointing out the the generic
solution could also be just returning the initial Connection ID because the
HMAC in this setup provides not stronger guarantees as far as I can tell.
The only guarantee it provides is that that payload has not been tampered
with, but that is for the handshake to decide, and the handshake goes to
great lengths to support extensible cryptography (for better or worse).
I don't think it is actually for the handshake to decide. The handshake
responds
to totally bogus data by reporting handshake failure, not by rejecting the
questionable
packet. For this reason it's more desirable to have the integrity check at
the layer
below.
WRT to returning the initial connection ID, in order to achieve the right
properties
you need to return it in *every* server packet before crypto is
established, or you
have potential problems. This seems goofy when you can just shove it in the
integrity check and have packet rejection at the lower layer.
|
I'm just going to throw this CLMUL hash into the equation, just for reference: Faster 64-bit universal hashing using carry-less multiplications |
I believe that we fixed this with the change to encryption for all packets. |
A Version Negotiation (VN) packet now contains a server-chosen connection ID and echoes the client's packet number, for a client to be able to validate that the server did see the client's packet.
There are no rules around what a client should do on receiving VN packets with random IDs and packet numbers that do not match. If the client just drops them on the floor, an attacker can send a bunch of VN packets with an arbitrary connection ID and with random packet numbers, hoping to kill the client's ongoing handshake.
Is 4 bytes of entropy enough to prevent this DoS?
The text was updated successfully, but these errors were encountered: