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

Fix for off-path migration attack #2033

Merged
merged 5 commits into from Dec 4, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
88 changes: 72 additions & 16 deletions draft-ietf-quic-transport.md
Expand Up @@ -1751,12 +1751,15 @@ the one to which the PATH_CHALLENGE was sent, path validation is considered to
have failed, even if the data matches that sent in the PATH_CHALLENGE.

Additionally, the PATH_RESPONSE frame MUST be received on the same local address
from which the corresponding PATH_CHALLENGE was sent. If a PATH_RESPONSE frame
is received on a different local address than the one from which the
PATH_CHALLENGE was sent, path validation is considered to have failed, even if
the data matches that sent in the PATH_CHALLENGE. Thus, the endpoint considers
the path to be valid when a PATH_RESPONSE frame is received on the same path
with the same payload as the PATH_CHALLENGE frame.
from which the corresponding PATH_CHALLENGE was sent. An endpoint considers the
path to be valid when a PATH_RESPONSE frame is received on the same path with
the same payload as the PATH_CHALLENGE frame.

If a PATH_RESPONSE frame is received on a different local address than the one
from which the PATH_CHALLENGE was sent, path validation is not considered to be
successful, even if the data matches the PATH_CHALLENGE. This doesn't result in
path validation failure, as it might be a result of a forwarded packet (see
{{off-path-forward}}) or misrouting.


## Failed Path Validation
Expand All @@ -1766,7 +1769,8 @@ abandons its attempt to validate the path.

Endpoints SHOULD abandon path validation based on a timer. When setting this
timer, implementations are cautioned that the new path could have a longer
round-trip time than the original.
round-trip time than the original. A value of three times the current
Retransmittion Timeout (RTO) as defined in {{QUIC-RECOVERY}} is RECOMMENDED.
Copy link
Contributor

Choose a reason for hiding this comment

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

This won’t work out well when switching from a 10ms WiFi.
I don’t think any value derived from the current RTT helps here. We don’t have any information about the new path, so I suggest we define a constant duration.

Copy link
Contributor

Choose a reason for hiding this comment

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

I had the same thought, or a minimum value of sorts.

Copy link
Member Author

Choose a reason for hiding this comment

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

I considered that, but we still have a minimum on the RTO, which should cover this case well enough.


Note that the endpoint might receive packets containing other frames on the new
path, but a PATH_RESPONSE frame with appropriate data is required for path
Expand Down Expand Up @@ -1891,7 +1895,7 @@ After verifying a new client address, the server SHOULD send new address
validation tokens ({{address-validation}}) to the client.


### Handling Address Spoofing by a Peer {#address-spoofing}
### Peer Address Spoofing {#address-spoofing}

It is possible that a peer is spoofing its source address to cause an endpoint
to send excessive amounts of data to an unwilling host. If the endpoint sends
Expand All @@ -1914,7 +1918,7 @@ If an endpoint skips validation of a peer address as described in
{{migration-response}}, it does not need to limit its sending rate.


### Handling Address Spoofing by an On-path Attacker {#on-path-spoofing}
### On-Path Address Spoofing {#on-path-spoofing}

An on-path attacker could cause a spurious connection migration by copying and
forwarding a packet with a spoofed address such that it arrives before the
Expand All @@ -1938,6 +1942,55 @@ Note that receipt of packets with higher packet numbers from the legitimate peer
address will trigger another connection migration. This will cause the
validation of the address of the spurious migration to be abandoned.


### Off-Path Packet Forwarding {#off-path-forward}

An off-path attacker that can observe packets might forward copies of genuine
packets to endpoints. If the copied packet arrives before the genuine packet,
this will appear as a NAT rebinding. Any genuine packet will be discarded as a
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be more precise in describing the attack:

  • when racing packets to the server, the attacker uses his own sender address on the UDP packet
  • when forwarding packets to the client, the attacker doesn’t spoofs the server’s address

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think that we need a precise description of the attack. This is already far too many words.

duplicate. If the attacker is able to continue forwarding packets, it might be
able to cause migration to a path via the attacker. This places the attacker on
path, giving it the ability to observe or drop all subsequent packets.

Unlike the attack described in {{on-path-spoofing}}, the attacker can ensure
that the new path is successfully validated.

This style of attack relies on the attacker using a path that is approximately
as fast as the direct path between endpoints. The attack is more reliable if
relatively few packets are sent or if packet loss coincides with the attempted
attack.

A non-probing packet received on the original path that increases the maximum
received packet number will cause the endpoint to move back to that path.
Eliciting packets on this path increases the likelihood that the attack is
unsuccessful. Therefore, mitigation of this attack relies on triggering the
exchange of packets.

In response to an apparent migration, endpoints MUST validate the previously
active path using a PATH_CHALLENGE frame. This induces the sending of new
packets on that path. If the path is no longer viable, the validation attempt
will time out and fail; if the path is viable, but no longer desired, the
validation will succeed, but only results in probing packets being sent on the
path.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is all heuristics, we may want to be a bit more explicit. If the destination CID in the packet is new, then the migration is more likely to be voluntary. If the address family is IPv6, NAT rebinding is not expected quite as much, even with NAT66, since NAT66 is very unlikely to run out of address space. If the last rebinding happened fewer than X seconds ago, this is probably very suspicious. Etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

The point here is that this isn't heuristics-based decision-making. It's currently arranged to be mechanical. The only discretionary part is the rate at which probes are generated. I think that the right thing to do is acknowledge that heuristics might be used to make this defense more robust and to mention some of the things you point to.

An endpoint that receives a PATH_CHALLENGE on an active path SHOULD send a
non-probing packet in response. If the non-probing packet arrives before any
copy made by an attacker, this results in the connection being migrated back to
the original path. Any subsequent migration to another path restarts this
entire process.

This defense is imperfect, but this is not considered a serious problem. If the
path via the attack is reliably faster than the original path despite multiple
attempts to use that original path, it is not possible to distinguish between
attack and an improvement in routing.

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, yeah, except if the improvement in routing only last for a short while, and after that the connection is dropped.

Copy link
Member

@kazuho kazuho Nov 22, 2018

Choose a reason for hiding this comment

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

Doesn't the connection simply move back to the original path (with a higher RTT) once the attacker stops racing the packets? So I think that calling the attacker an "improvement in routing" is correct.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, since there will still be duplicate packets from the client and you can't make the client actually change the remote address that it sends to. So even if the attack succeeds, if the attacker stops delivering packets (or even starts delivering them more slowly), I think you would automatically just go back to the original path (as long as the client is still sending).

My understanding here is that this overall change is mostly necessary to prompt traffic from a client that might otherwise have quiesced.

Copy link
Member Author

Choose a reason for hiding this comment

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

The risk is that the attacker can convince a peer that the connection is dead, meaning that no more packets are sent. The interaction between validation timers and dead path detection probably need some work.

An endpoint could also use heuristics to improve detection of this style of
attack. For instance, NAT rebinding is improbable if packets were recently
received on the old path, similarly rebinding is rare on IPv6 paths. Endpoints
can also look for duplicated packets. Conversely, a change in connection ID is
more likely to indicate an intentional migration rather than an attack.


## Loss Detection and Congestion Control {#migration-cc}

The capacity available on the new path might not be the same as the old path.
Expand All @@ -1963,13 +2016,16 @@ multiple paths will still send ACK frames covering all received packets.

While multiple paths might be used during connection migration, a single
congestion control context and a single loss recovery context (as described in
{{QUIC-RECOVERY}}) may be adequate. A sender can make exceptions for probe
packets so that their loss detection is independent and does not unduly cause
the congestion controller to reduce its sending rate. An endpoint might set a
separate timer when a PATH_CHALLENGE is sent, which is cancelled when the
corresponding PATH_RESPONSE is received. If the timer fires before the
PATH_RESPONSE is received, the endpoint might send a new PATH_CHALLENGE, and
restart the timer for a longer period of time.
{{QUIC-RECOVERY}}) may be adequate. For instance, an endpoint might delay
switching to a new congestion control context until it is confirmed that an old
path is no longer needed (such as the case in {{off-path-forward}}).

A sender can make exceptions for probe packets so that their loss detection is
independent and does not unduly cause the congestion controller to reduce its
sending rate. An endpoint might set a separate timer when a PATH_CHALLENGE is
Copy link
Contributor

Choose a reason for hiding this comment

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

...which makes sense, given that you don't retransmit PATH_CHALLENGE or PATH_RESPONSE, maybe we should note that here or nearby as well?

sent, which is cancelled when the corresponding PATH_RESPONSE is received. If
the timer fires before the PATH_RESPONSE is received, the endpoint might send a
new PATH_CHALLENGE, and restart the timer for a longer period of time.
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we'd already addressed this elsewhere, but I can't find it anymore, so this looks good.
My memory was that we said to retransmit PATH_CHALLENGE based on a timer until you got a response or decide that validation failed, although now we have three states for validation result. If we have that elsewhere (and I just missed it) then we should reconcile with this.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is just the old text, with the paragraph split to allow for the new text. If you have a suggestion here, that would be great, but I can't figure out how to add that without doing a lot of damage to the existing text.



## Privacy Implications of Connection Migration {#migration-linkability}
Expand Down