[quicwg/base-drafts] Request forgery attacks (#3995)
Martin Thomson <notifications@github.com> Wed, 12 August 2020 06:29 UTC
Return-Path: <noreply@github.com>
X-Original-To: quic-issues@ietfa.amsl.com
Delivered-To: quic-issues@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 614363A1086 for <quic-issues@ietfa.amsl.com>; Tue, 11 Aug 2020 23:29:22 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.858
X-Spam-Level:
X-Spam-Status: No, score=-1.858 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, MAILING_LIST_MULTI=-1, NUMERIC_HTTP_ADDR=1.242, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=github.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7HYTczlezu6s for <quic-issues@ietfa.amsl.com>; Tue, 11 Aug 2020 23:29:18 -0700 (PDT)
Received: from out-17.smtp.github.com (out-17.smtp.github.com [192.30.252.200]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B332A3A1088 for <quic-issues@ietf.org>; Tue, 11 Aug 2020 23:29:18 -0700 (PDT)
Received: from github-lowworker-45eca55.ac4-iad.github.net (github-lowworker-45eca55.ac4-iad.github.net [10.52.25.70]) by smtp.github.com (Postfix) with ESMTP id D1D225C0E87 for <quic-issues@ietf.org>; Tue, 11 Aug 2020 23:29:17 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=github.com; s=pf2014; t=1597213757; bh=vBqX0NpiRMIMMb4QX2tB4Vi1YAOgvxKKzOLNT6ahAvs=; h=Date:From:Reply-To:To:Cc:Subject:List-ID:List-Archive:List-Post: List-Unsubscribe:From; b=a3jcWWhmBDF7h5SC5QH+jrT4dd4U62nwncZSi4XwdAPoFmiQPtCx9V8iaPM9hOabI k5yJP2GaVOg/dllhAXtMRQoEuBQFs+7z/Oq8cbwYwFkLNcukqVrAGCNwv8BLyT/5dI cup30xGB8HMxGNXZQ3B7d3Yy0/IaYACDaa5/OTEE=
Date: Tue, 11 Aug 2020 23:29:17 -0700
From: Martin Thomson <notifications@github.com>
Reply-To: quicwg/base-drafts <reply+AFTOJK3V3V5AZOOYYBQKKMV5H5WT3EVBNHHCQYGADU@reply.github.com>
To: quicwg/base-drafts <base-drafts@noreply.github.com>
Cc: Subscribed <subscribed@noreply.github.com>
Message-ID: <quicwg/base-drafts/issues/3995@github.com>
Subject: [quicwg/base-drafts] Request forgery attacks (#3995)
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_5f338c3dc0d5b_460c16f850599b"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: martinthomson
X-GitHub-Recipient: quic-issues
X-GitHub-Reason: subscribed
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: quic-issues@ietf.org
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic-issues/TEQ6oC7QWN3AYojodhky2_Ukmbc>
X-BeenThere: quic-issues@ietf.org
X-Mailman-Version: 2.1.29
List-Id: Notification list for GitHub issues related to the QUIC WG <quic-issues.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic-issues/>
List-Post: <mailto:quic-issues@ietf.org>
List-Help: <mailto:quic-issues-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 12 Aug 2020 06:29:22 -0000
# What is server-side request forgery? Server-side request forgery (SSRF) is an attack technique where a malicious server takes advantage of a client that is in a privileged location of the network to attack unprotected servers from the client location. This relies on there being a server that has no protections at all. This server takes actions without authenticating the requester. That is, the server assumes that because the request reached it, the request was authorized. These servers are often deployed with the assumption that access to the network is tightly controlled and so rely on that access control alone. Historically, these servers were very common in enterprise networks, but that is no longer best practice. It is. however, still common to find services deployed on loopback addresses that fail to properly authenticate requests. A simple example exploits bugs in URL parsing of clients to embed messages. The attacker asks the client to navigate to `http://10.0.0.1¤\r\nEXPLOIT BUG\r\n/`. The client connects to the IP address, ignoring the junk, but includes all of the junk in the TLS Server Name Indication (SNI) field it sends. As a result, data that is controlled by the attacker is sent in the clear to the vulnerable server. For this style of attack, the trick is finding a server that will read past the TLS junk that precedes the instruction to find and execute the instruction. And don't laugh, [it wasn't that hard to find servers that did this](https://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf) (that paper describes a form of SSRF as well, but the victim was a middlebox). With TLS (and presumably DTLS), is also possible to use [session IDs](https://github.com/jmdx/TLS-poison/) or session tickets to the same end, without relying on bugs in the client. SSRF often doesn't produce any feedback directly to the attacker, but it can be used to establish control over the vulnerable host, which might lead to opening communication channels. # How QUIC enables SSRF >From the protocol side, the key enablers for SSRF are mechanisms that allow an endpoint to control the **destination address** and part of the **(unencrypted) content of messages** sent by a peer. So what opportunities are there for SSRF in QUIC? With some exceptions, QUIC offers few options for an adversary to send to a destination address that does not understand QUIC. As far as controlling the content of messages goes, Initial protection using the client-chosen Destination Connection ID is pretty effective, but the same does not apply to other messages. The fact that this is an encrypted protocol doesn't help as much as you would like, thanks to use of XOR-based stream ciphers. That means we need to examine the cases where destinations can be controlled, as those are where QUIC is most vulnerable. ## Controlling packet destination The destination for the very first Initial packets from a client is open to server control. An attacker can, through control over the IP addresses returned by DNS or Alt-Svc, affect where connection attempts go. Once a connection is established, address validation is used to ensure that a target address is willing to communicate. However, address validation requires that some packets be sent to an address prior to validating it. As migration is currently only possible for a client, this means we need to consider the potential for clients to mount this style of attack using a server. This requires source address spoofing to fake a connection migration. As servers are not permitted to initiate migration, preferred address is the only way that a server can cause a client to send any other type of packet to an address that it does not control. For a completely new connection, we can assume that the victim doesn't support QUIC and does not respond with valid QUIC messages. Therefore, it is safe to assume that the client won't send any other type of message other than Initial in cases other than when it migrates to a preferred address. ## Controlling content For content, the most obvious fields are the Destination Connection ID in every packet and the Token field of Initial packets. Use of encryption for Initial messages and the randomized destination connection ID ensures that a server controls none of the message plaintext for Initial messages. This means that Initial messages are mostly safe. The exception here is the Token field, which is server controlled. Encryption doesn't help a great deal. As the attacker has encryption keys and we use ciphers that are effectively stream ciphers, an attacker has a reasonable chance of predicting how encryption will transform a large proportion of packets. An attacker that can control the content of frames and can predict the packet number that is used can therefore provide content that encrypts to ciphertext of its choosing. This relies on being able to predict frame placement, but implementations are fairly consistent and so are expected to be somewhat predictable. Browsers in particular offer a number of ways for adversaries to control client behavior. Similarly, servers often allow clients to create or alter content in ways that might be suited to this style of exploitation. # Concrete attacks As altering content seems to be broadly feasible, our primary focus needs to be on those cases where packets are sent to an address that has not been validated. This leaves three avenues to explore more: preferred address, address validation tokens in Initial packets, and spoofed migrations by a client. ## Preferred address The preferred address is a pretty good SSRF enabler. The entire point is to enable server specify an address, so controlling destination is trivial. For content, we only have short headers as a client cannot migrate prior to confirming the handshake, after which we only use packets with short headers. The effect is that a client will send a UDP datagram containing one uncontrolled byte (this is in the range that includes all ASCII alphabet characters) and then up to 20 attacker-controlled bytes to a destination of the attacker's choice. The remainder of the datagram cannot be directly controlled by the attacker. However, the attacker has encryption keys and can probably predict the packet number. Therefore, if it can control the content of frames, it has an opportunity to affect what appears in the encrypted datagram. Thus we need to consider what might be included in this packet. If we look at probing frames, the packet likely contains PATH_CHALLENGE, which is explicitly not controlled. Other likely candidates for inclusion in this packet are the other probing frames (PADDING, NEW_CONNECTION_ID, and maybe PATH_RESPONSE), which offer an attacker limited options for control, even if frame composition is attacker controlled. We can also assume here that the attacker is unable to effectively control the encoded packet number, so it would have to work around those bytes. Frames that carry application data (STREAM or DATAGRAM) are definitely more open to control. In some settings (browsers in particular) the contents of these frames might be controlled by the attacker. Therefore, frames carrying application data offer the attacker the means of indirectly controlling large portions of plaintext. This only depends on being able to predict packet numbers and to know the likely placement of frames in the packet, both of which have to be regarded as easy. That said, if clients refuse to migrate to a preferred address without first validating it, this option will not be useful to an attacker. ## Initial tokens NEW_TOKEN provides a server with some ability to control both destination and content. The attacker can alter DNS records or use Alt-Svc to select a target. The server has less control over the Initial packet generally, but the token is only limited in length by the size of the packets that carry it, so it provides a lot more space to play with than a connection ID. There is a little more uncontrolled junk (at least 16 bytes) ahead of the token than with preferred address. That junk is not likely to be a major barrier, especially with the extra space on offer. The TLS attacks mentioned above deal with more than twice this amount of junk. Retry also provides an opportunity as the server selects the connection ID and token. As the server is unable to change the IP address the client uses after a Retry, Retry cannot be used to select a target. (As an aside for Retry, controlling the connection ID provides control over the Initial encryption keys. In theory, this removes the defense offered by Initial protection as the server can choose connection IDs until encryption produces the content it desires. As the client is required to use the same CRYPTO frames, the attacker only has to iterate through values until it gets what it wants. However, this control is limited to a small number of bytes as the cost increases exponentially with the number of bits that the server wishes to control. Using the Token field is considerably easier.) ## Client spoofed migrations This case is the inverse of SSRF in that it is the client that performs the attack with the goal of using the privileged position of the server. To mount the attack, the client needs to inject its payload into a connection ID and then spoof its source address to match the intended target. ## Observable effects All of these cases can be exploited without observable effect. Packets are sent as part of an existing connection that continues to operate normally, or packets are sent as part of a connection establishment that is performed while another connection remains active (assuming that NEW_TOKEN is used with Alt-Svc and not DNS targeting; DNS targeting could be more obvious). This means that the exploits have no natural pressures that force them to be exposed. The victim might notice if the attacker has to try many times to be successful or the endpoint that is mounting the attack might notice unusual activity, but only if there are measures in place to look for an attack. Both preferred address and NEW_TOKEN do require that new connections be established, which might limit the rate at which an attacker can retry the attack. Spoofing addresses is not limited in the same way. If the same connection ID is used, then the attack is limited only by the rate at which the server is willing to use the address (or addresses). # Do we care? Yes, we should care. Though it takes a horribly insecure configuration to be vulnerable to this sort of attack, that does not mean attacks won't happen or that clients or the IETF won't be held responsible. See also the law of the internet: *blame attaches to the last thing that changed*. Browsers are very careful in defending against this style of attack. CORS is a horrible tax that every cross origin request pays for this. That doesn't mean that only browsers need to worry about defenses. There are a lot of deployments that understand this attack well and have deployed defenses for TCP. These likely include a suite of patterns that can be used to identify and defend against known attacks. The risk with QUIC is that these defenses are less mature or non-existent for UDP. This analysis assumes that removing any of these features that might be exploited this way is not desirable. It further assumes that adding new mechanisms, particularly those that might degrade performance, is not tenable. These problems might be worth doing something about, but they are still largely the fault of servers that act on unauthenticated instructions. It should not be entirely up to QUIC to address these concerns. Anything that makes QUIC substantially worse to protect such servers is not worth considering. For instance, control over cleartext could be achieved using [the masking technique employed by Web Sockets](https://tools.ietf.org/html/rfc6455#section-5.3). Requiring additional round trips for address validation might help narrow the options for attack. However, both would likely adversely affect performance. That doesn't mean doing absolutely nothing, as that would not be responsible. # What can we do? For NEW_TOKEN, we have a mitigation that seems pretty effective: don't send the token. As the protocol does not depend on successful use of a token, we can simply recommend that clients not include a token in Initial packets when the server address changes. We might allow heuristics so that tokens can be used when the server addresses stays within the same subnet (of unspecified size) or same AS or something along those lines. That should retain most of the value of the mechanism without dramatically increasing exposure. Even if heuristics are used, this would require that the attacker be adjacent to the victim, which should be effective in blunting the attack. [BCP 38](https://tools.ietf.org/html/bcp38) seems like the best countermeasure for attacks that use client address spoofing. Assuming that the attacker isn't in the same network, ingress filtering will easily prevent this attack. Aiming to prevent control over the cleartext of packets is difficult and likely to be ineffective. Spoofing can be made to look like NAT rebinding. Insisting on address validation prior to validating the address is an undesirable imposition that will affect performance pretty badly relative to just making a new connection. If we assume the use of ingress filtering where there are servers that might be vulnerable, it should not be necessary to require address validation. For spoofing, we could recommend that implementations not send toward an address that has failed address validation for some period. This will limit the rate at which spoofing might be used. ## Preferred address mitigations Unfortunately, there doesn't appear to be a single crisp thing we can recommend for preferred addresses. One possible option we have is to prohibit the use of preferred address to elevate privileges. That is, prevent a server from picking a preferred address from a portion of the network that might have different protections. (Does anyone remember Microsoft's concept of Zones from Internet Explorer days?) How we identify this elevation becomes challenging though, and it is not always clear that an apparent "elevation" is truly illegitimate. We might advise clients to avoid preferred addresses that go from an apparently public IP to a link-local or 1918 address, but that sort of restriction could affect real use cases in ways that we don't want. To give a concrete example, an ISP might operate their network in a private address range and use NAT for traffic that leaves the network. A server that is hosted inside that network might be reachable using a public address (which might be unicast), but it could offer clients a more direct connection using the preferred address mechanism that includes a private address. Prohibiting use of loopback (127.0.01 or ::1) preferred addresses from non-loopback servers seems like it might be safe, but that too might preemptively exclude valid uses. I don't have any such use case right now, so it seems like this is a reasonable recommendation. People who might eventually discover a use case will need to deal with that recommendation. You might consider sending a garbage long header packet prior to address validation, but that doesn't really change the dynamics much. A long header adds 5 more bytes ahead of the attacker-controlled connection ID. That might make it marginally harder to exploit, but it's not enough of an improvement to justify recommending it. We can prohibit the sending of non-probing frames to a preferred address prior to address validation. That's a pretty big change, but I think that it is reasonable given the attack. That reduces the amount of controlled cleartext to the connection ID, not the majority of the packet. Restricting to non-probing frames adds a performance hit if a client is forced to migrate before acting on a preferred address, but that seems like a tolerable loss. # Summary This seems like a lot. I've certainly written a lot of words. But I think that the attack is not that serious. The protections we might deploy for two of the three attacks aren't that onerous, and we can do a little bit to mitigate risk for preferred addresses. The important thing here is to ensure that we document the risks. This is one of those areas where building a protocol on top of UDP exposes new operational risks. I'm proposing that we simply document the risks and add some small mitigations provided that they don't cost much. I'll propose a PR with that proposal. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/quicwg/base-drafts/issues/3995
- [quicwg/base-drafts] Request forgery attacks (#39… Martin Thomson
- Re: [quicwg/base-drafts] Request forgery attacks … MikkelFJ
- Re: [quicwg/base-drafts] Request forgery attacks … Kazuho Oku
- Re: [quicwg/base-drafts] Request forgery attacks … Kazuho Oku
- Re: [quicwg/base-drafts] Request forgery attacks … Martin Thomson
- Re: [quicwg/base-drafts] Request forgery attacks … MikkelFJ
- Re: [quicwg/base-drafts] Request forgery attacks … Mike Bishop
- Re: [quicwg/base-drafts] Request forgery attacks … Martin Thomson
- Re: [quicwg/base-drafts] Request forgery attacks … Kazuho Oku
- Re: [quicwg/base-drafts] Request forgery attacks … Mike Bishop
- Re: [quicwg/base-drafts] Request forgery attacks … Lucas Pardue
- Re: [quicwg/base-drafts] Request forgery attacks … Jana Iyengar