RFC 8470

Using Early Data in HTTP

πŸ“… published September 2018, from ietf

RFC 8470: Using Early Data in HTTP πŸŽ€

Okay bestie, this is RFC 8470, and it's called "Using Early Data in HTTP" πŸ¦‹. It's a Standards Track document from September 2018, with ISSN 2070-1721. Three people wrote it: M. Thomson from Mozilla, M. Nottingham from Fastly, and W. Tarreau from HAProxy Technologies πŸ’œ. The title block doesn't list anything this RFC obsoletes or updates, so it's out here doing its own thing ✨

Abstract

Okay so, using TLS early data creates a chance for a replay attack πŸ™ˆ This document defines mechanisms that let clients tell servers about HTTP requests that get sent in early data. It also describes techniques that use those mechanisms to lower the risk of replay. Main character energy for keeping your requests safe πŸ’…

Status of This Memo

This is an Internet Standards Track document. 🌸

It's a product of the Internet Engineering Task Force (IETF), and it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 7841.

Info about the current status of this document, any errata, and how to give feedback on it can be found at https://www.rfc-editor.org/info/rfc8470 πŸ“

Copyright (c) 2018 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ”’

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they're in effect on the date this document was published. Please actually read these, bestie, because they explain your rights and restrictions for this document. Code Components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License 🫢

Table of Contents

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
  1.1.  Conventions and Definitions . . . . . . . . . . . . . . .   3
2.  Early Data in HTTP  . . . . . . . . . . . . . . . . . . . . .   3
3.  Supporting Early Data in HTTP Servers . . . . . . . . . . . .   3
4.  Using Early Data in HTTP Clients  . . . . . . . . . . . . . .   5
5.  Extensions for Early Data in HTTP . . . . . . . . . . . . . .   6
  5.1.  The Early-Data Header Field . . . . . . . . . . . . . . .   7
  5.2.  The 425 (Too Early) Status Code . . . . . . . . . . . . .   8
6.  Security Considerations . . . . . . . . . . . . . . . . . . .   8
  6.1.  Gateways and Early Data . . . . . . . . . . . . . . . . .   8
  6.2.  Consistent Handling of Early Data . . . . . . . . . . . .   9
  6.3.  Denial of Service . . . . . . . . . . . . . . . . . . . .   9
  6.4.  Out-of-Order Delivery . . . . . . . . . . . . . . . . . .   9
7.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  10
8.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  10
  8.1.  Normative References  . . . . . . . . . . . . . . . . . .  10
  8.2.  Informative References  . . . . . . . . . . . . . . . . .  11
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  11
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  12

1. Introduction ✨

Okay so, TLS 1.3 [TLS13] brings in early data, which you might also hear called zero round-trip time (0-RTT) data πŸš€ If the client has talked to the same server recently, early data lets it send data to the server in the first round trip of a connection, without waiting for the TLS handshake to finish.

When it's used with HTTP [HTTP], early data lets clients send requests right away, skipping the one or two round-trip delays the TLS handshake would normally need. It's a huge performance glow-up, but it also has some big limitations πŸ’€

The main risk with early data is that an attacker might capture the request(s) inside it and replay them. TLS [TLS13] describes techniques that make it harder for an attacker to replay a request successfully. The catch is that these techniques can be annoying to deploy, and there's still a small chance an attack works 😭

Heads up that this is different from automatic or user-started retries. Replays are started by an attacker, and the client has no idea it's happening πŸ™ˆ

To help stop replays in HTTP, this document gives an overview of techniques servers can use to control these risks. It also sets requirements for clients that send requests in early data 🫢

The advice in this document also applies to using 0-RTT in HTTP over QUIC [HQ] 🌈

1.1. Conventions and Definitions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. πŸ“–

2. Early Data in HTTP πŸ¦‹

Conceptually, early data gets stuck together with other application data to make one single stream. That means requests can be totally inside early data, or only part of a request might be early. In a multiplexed protocol, like HTTP/2 [RFC7540] or HTTP/QUIC [HQ], several requests might be partly delivered in early data πŸ“

The model this document assumes is that once the TLS handshake finishes, the early data received on that TLS connection is known to not be a replayed copy of that data. BUT it's important to know that this does NOT mean early data won't be replayed, or hasn't been replayed, on another connection πŸ‘€

3. Supporting Early Data in HTTP Servers 🧚

A server decides whether to let a client send early data on future connections when it sends the TLS session ticket. That's the moment it chooses, and it's a big decision ✨

TLS [TLS13] mandates the use of replay detection strategies that make it harder for an attacker to successfully replay early data. These anti-replay techniques reduce the chance of data being replayed, but they don't fully get rid of it. They do make sure there's a fixed upper limit on how many replays can happen πŸ”’

When a server turns on early data, it has a few techniques to lower the risk of replay:

  1. The server can reject early data at the TLS layer. A server can't pick and choose here, so every request sent in early data gets thrown out πŸ—‘οΈ
  2. The server can choose to delay processing early data until after the TLS handshake completes. By waiting, it makes sure only a connection that finished the handshake gets used for the request(s) inside. That gives the server some peace of mind that the early data wasn't replayed. If the server gets multiple requests in early data, it can decide whether to hold off on HTTP processing one request at a time 🌸
  3. The server can make a client retry individual requests without using early data, by responding with the 425 (Too Early) status code (Section 5.2) when it thinks the risk of replay is too high πŸ’…

All three of these techniques work equally well, so a server can pick whichever one suits it best πŸŽ€

How much replay risk a request can tolerate depends on the resource it's acting on, so only the origin server actually knows that. The main danger with early data is what a server does while processing a request. Processing a duplicated request might cause duplicated effects and side effects. Appendix E.5 of [TLS13] also describes other effects that come from processing duplicated requests 😬

The request method's safety ([RFC7231], Section 4.2.1) is one way to figure this out. BUT some resources cause side effects even with safe methods, so you can't rely on this one everywhere πŸ™…β€β™€οΈ

It is RECOMMENDED that origin servers let resources explicitly say whether early data is appropriate in requests. Without that explicit info, origin servers MUST either reject early data or use the techniques in this document to make sure requests aren't processed before the TLS handshake completes πŸ”₯

A request might be sent partly in early data, with the rest sent after the handshake completes. This doesn't necessarily change how that request gets handled, because what matters is when the server starts acting on the contents of a request. Any time any server instance might start processing before the handshake finishes, ALL server instances need to account for the possibility of early data being replayed, and how that could affect that processing (see also Section 6.2) 🧠

A server can partly process requests that are incomplete. Parsing header fields, without acting on the values, and figuring out request routing are probably safe from side effects, but other actions might not be 🍰

Intermediary servers don't have enough info to decide whether early data can be processed. So Section 5.2 describes a way for the origin to signal to them that a particular request isn't appropriate for early data. Intermediaries that accept early data MUST implement that mechanism πŸ’œ

Note that a server can't choose to selectively reject early data at the TLS layer. TLS only lets a server accept all early data or none of it. Once a server has decided to accept early data, it MUST process all requests in early data, even if the server rejects the request by sending a 425 (Too Early) response 😀

A server can limit how much early data it takes with the "max_early_data_size" field of the "early_data" TLS extension. That can be used to avoid committing an arbitrary amount of memory to requests the server might defer until the handshake completes 🌈

4. Using Early Data in HTTP Clients ✨

okay so, a client that wants to use early data just starts sending HTTP requests right away, the moment it has sent its TLS ClientHello πŸš€

clients basically get to decide which requests ride along in early data, which means they're the ones in charge of the replay risk πŸ’… absent any other info, clients MAY send requests with safe HTTP methods ([RFC7231], Section 4.2.1) in early data when it's available, but they MUST NOT send unsafe methods (or methods whose safety isn't known) in early data. no exceptions, bestie πŸ™…β€β™€οΈ

if the server rejects early data at the TLS layer, the client MUST start sending again as though the connection were brand new πŸ”„ this could mean switching to a different negotiated protocol [ALPN] than the one it optimistically used for early data. anything that got sent in early data will need to be sent again, unless the client decides to give up on those requests πŸ₯€

now the spicy part, the replay attack 🫣 an attacker grabs a connection that's using early data and copies that early data over to another server instance. that second instance accepts and processes it, even though it never completes the TLS handshake 😱 then the attacker lets the original connection finish. even if the early data gets flagged as a duplicate and rejected, the first server instance might still let the connection complete. if the client then retries the requests that went out in early data, those requests get processed twice πŸ’€

replays can also happen if there are multiple server instances that accept early data, or if the same server accepts early data more than once (though that second one would be violating the requirements in Section 8 of [TLS13]) πŸ™ˆ

clients that use early data MUST retry requests when they get a 425 (Too Early) status code; see Section 5.2 πŸ”

an intermediary MUST NOT use early data when forwarding a request unless early data was used on a previous hop, or it knows the request can be retried safely without consequences (typically through out-of-band configuration) 🧐 without better info, an intermediary can only use early data if the request either arrived in early data or arrived with the Early-Data header field set to "1" (see Section 5.1) πŸŽ€


5. Extensions for Early Data in HTTP 🌸

because HTTP requests can span multiple "hops", it's necessary to explicitly communicate whether a request was sent in early data on a previous hop πŸ¦‹ it's also necessary to have some way of explicitly triggering a retry when early data isn't wanted, and finally, you need to know whether the client will actually do that retry 🀞

so two signaling mechanisms are defined ✨

  • The Early-Data header field is included in requests that might have been forwarded by an intermediary before the TLS handshake with its client completed.
  • The 425 (Too Early) status code is defined for a server to say that a request couldn't be processed because of the consequences of a possible replay attack.

these are designed to get user agents and origin servers coordinating better on early data, including when a gateway (also "reverse proxy", "Content Delivery Network", or "surrogate") is in the picture πŸ’–

gateways usually don't have specific info about whether a given request can be processed safely when sent in early data 😬 in lots of cases, only the origin server has what it needs to decide if the replay risk is acceptable. these extensions let the gateway and its origin server coordinate 🫢

5.1. The Early-Data Header Field πŸ’œ

the Early-Data request header field says that the request was conveyed in early data AND that the client understands the 425 (Too Early) status code πŸ™Œ

it has just one valid value: "1" 1️⃣ the syntax is defined by the following ABNF [ABNF]:

Early-Data = "1"

for example:

GET /resource HTTP/1.0
Host: example.com
Early-Data: 1

an intermediary that forwards a request before the TLS handshake with its client completes MUST send it with the Early-Data header field set to "1" (so it adds the field if it isn't already there) πŸͺ„ an intermediary MUST use the Early-Data header field if the request might have been subject to a replay and might already have been forwarded by it or another instance (see Section 6.2) πŸ”

an intermediary MUST NOT remove this header field if it's present in a request 🚫 and Early-Data MUST NOT appear in a Connection header field πŸ™…β€β™€οΈ

the Early-Data header field isn't meant for user agents (the original initiator of a request) πŸ™ˆ sending a request in early data implies the client understands this spec and is willing to retry a request when it gets a 425 (Too Early) status code. a user agent that sends a request in early data doesn't need to include the Early-Data header field πŸ’…

a server can't make a request that contains the Early-Data header field safe to process just by waiting for the handshake to complete πŸ™…β€β™€οΈ a request marked with Early-Data was sent in early data on a previous hop. requests that contain the Early-Data header field and can't be safely processed MUST be rejected with the 425 (Too Early) status code 🚫

the Early-Data header field carries a single bit of information, and clients MUST include at most one instance 🧸 multiple or invalid instances of the header field MUST be treated by a server as equivalent to a single instance with a value of 1 🫧

an Early-Data header field MUST NOT be included in responses or request trailers πŸ™…β€β™€οΈ

5.2. The 425 (Too Early) Status Code 🌈

a 425 (Too Early) status code means the server is unwilling to risk processing a request that might be replayed 🫣

user agents that send a request in early data are expected to retry the request when they get a 425 (Too Early) response status code πŸ” a user agent SHOULD retry automatically, but any retries MUST NOT be sent in early data πŸ™…β€β™€οΈ

in all cases, an intermediary can forward a 425 (Too Early) status code πŸ’β€β™€οΈ intermediaries MUST forward a 425 (Too Early) status code if the request they received and forwarded contained an Early-Data header field 🫢 otherwise, an intermediary that receives a request in early data MAY automatically retry that request in response to a 425 (Too Early) status code, but it MUST wait for the TLS handshake to complete on the connection where it received the request ⏳

the server can't assume a client is able to retry a request unless the request was received in early data or the Early-Data header field is set to "1" πŸ€” a server SHOULD NOT emit the 425 status code unless one of these conditions is met πŸ™…β€β™€οΈ

the 425 (Too Early) status code is not cacheable by default πŸ—„οΈ and its payload isn't the representation of any identified resource πŸ™ˆ


6. Security Considerations πŸ’€

okay this section is serious, so buckle up 😭 using early data exposes a client to the risk that their request gets replayed 🚨 a retried or replayed request can produce different side effects on the server ✨ on top of those side effects, replays and retries might be used for traffic analysis to recover information about requests or the resources they target πŸ•΅οΈβ€β™€οΈ in particular, a replayed request might result in a different response, which could be observable from the length of protected data even if the content stays confidential πŸ‘€

6.1. Gateways and Early Data πŸšͺ

a gateway MUST NOT forward requests that were received in early data unless it knows that the origin server it'll forward to understands the Early-Data header field and will correctly generate a 425 (Too Early) status code πŸ™…β€β™€οΈ a gateway that's uncertain about origin server support for a given request SHOULD either delay forwarding the request until the TLS handshake with its client completes, or send a 425 (Too Early) status code in response ⏳

a gateway without at least one potential origin server that supports the Early-Data header field spends a lot of effort for what can, at best, be a modest performance benefit from early data 😩 if no origin server supports early data, it's more efficient to disable early data entirely πŸ’…

6.2. Consistent Handling of Early Data πŸ«‚

consistent treatment of a request that arrives in, or partially in, early data is critical to avoiding inappropriate processing of replayed requests πŸ”‘ if a request isn't safe to process before the TLS handshake completes, then ALL instances of the server (including gateways) need to agree and either reject the request or delay processing 🀝

disabling early data, delaying requests, or rejecting requests with the 425 (Too Early) status code are all equally good measures for mitigating replay attacks on requests that might be vulnerable to replay πŸ’– server instances can implement any of these measures and still be considered consistent, even if different instances use different methods πŸ¦‹ critically, this means it's possible to use different mitigations in reaction to other conditions, such as server load 🎯

a server MUST NOT act on early data before the handshake completes if it and any other server instance could make a different decision about how to handle the same data πŸ™…β€β™€οΈ

6.3. Denial of Service 🚨

accepting early data exposes a server to potential denial of service through replays of requests that are expensive to handle πŸ’Έ a server that's under load SHOULD prefer rejecting TLS early data as a whole, rather than accepting early data and selectively processing requests πŸ›‘ generating a 503 (Service Unavailable) or 425 (Too Early) status code often leads clients to retry requests, which could increase load πŸ“ˆ

6.4. Out-of-Order Delivery πŸŒ€

in protocols that deliver data out of order (such as QUIC [HQ]), early data can arrive after the handshake completes πŸ˜΅β€πŸ’« a server MAY process requests received in early data after handshake completion ONLY if it can rely on other instances correctly handling replays of the same requests 🫢


7. IANA Considerations πŸ“‹

this document registers the Early-Data header field in the "Permanent Message Header Field Names" registry located at <https://www.iana.org/assignments/message-headers> πŸ—‚οΈ

Header field name:  Early-Data

Applicable protocol:  http

Status:  standard

Author/Change controller:  IETF

Specification document(s):  This document

Related information:  (empty)

this document also registers the 425 (Too Early) status code in the "HTTP Status Codes" registry located at <https://www.iana.org/assignments/http-status-codes> πŸŽ€

Value:  425

Description:  Too Early

Reference:  This document

8. References πŸ“š

8.1. Normative References πŸ“šβœ¨

[ABNF] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[HTTP] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, DOI 10.17487/RFC7230, June 2014, <https://www.rfc-editor.org/info/rfc7230>.

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014, <https://www.rfc-editor.org/info/rfc7231>.

[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[TLS13] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

8.2. Informative References πŸ§ πŸ’…

[ALPN] Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[HQ] Bishop, M., "Hypertext Transfer Protocol (HTTP) over QUIC", Work in Progress, draft-ietf-quic-http-14, August 2018.

[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext Transfer Protocol Version 2 (HTTP/2)", RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.


Acknowledgments 🫢🌸

This doc was NOT easy to make, bestie 😭 The people below put in substantial work to make it way better and way more complete, and we are so grateful: David Benjamin, Subodh Iyengar, Benjamin Kaduk, Ilari Liusavaara, Kazuho Oku, Eric Rescorla, Kyle Rose, and Victor Vasiliev. Iconic behaviour from all of them πŸ‘‘


Authors' Addresses πŸ¦‹

Martin Thomson Mozilla

Email: martin.thomson@gmail.com

Mark Nottingham Fastly

Email: mnot@mnot.net

Willy Tarreau HAProxy Technologies

Email: willy@haproxy.org

πŸ“¦ where this page comes from