Which vulnerabilites does HTTP/2 prevent?

More specifically:

  • Does it prevent HTTP request smuggling?
  • Does it prevent HTTP response splitting / CRLF injection?

TLS related security features in HTTP/2

The concrete security improvements mentioned in the FAQ are related to TLS encryption: HTTP/2 MUST use at least TLS 1.2 and it support SNI. Also, HTTP/2 introduces a TLS 1.2 Cipher Suite Black List that implementations MAY treat as connection errors.

What does HTTP/2 do to improve security?

HTTP/2 defines a profile of TLS that is required; this includes the version, a ciphersuite blacklist, and extensions used.

See the spec for details.

There is also discussion of additional mechanisms, such as using TLS for HTTP:// URLs (so-called “opportunistic encryption”); see RFC 8164.

In addition to that, HTTP/2 provides secure compression features that enables you to have header compression while having TLS 1.2 compression disabled. From http2 explained:

6.5.1. Compression is a tricky subject

HTTPS and SPDY compression were found to be vulnerable to the BREACH and CRIME attacks. By inserting known text into the stream and figuring out how that changes the output, an attacker can figure out what's being sent in an encrypted payload.

Doing compression on dynamic content for a protocol - without becoming vulnerable to one of these attacks - requires some thought and careful consideration. This is what the HTTPbis team tried to do.

Enter HPACK, Header Compression for HTTP/2, which – as the name suggests - is a compression format especially crafted for http2 headers, and it is being specified in a separate internet draft. The new format, together with other counter-measures (such as a bit that asks intermediaries to not compress a specific header and optional padding of frames), should make it harder to exploit compression.

Does HTTP/2 prevent HTTP request smuggling?

HTTP request smuggling isn't really a vulnerability in HTTP/1.1 protocol itself, but the existence of two different ways of specifying how the request ends (Content-Length & Transfer-Encoding) leaves room for bad HTTP proxy server chain implementations. In HTTP/2 there's only one:

In short, HTTP/2 breaks down the HTTP protocol communication into an exchange of binary-encoded frames, which are then mapped to messages that belong to a particular stream, all of which are multiplexed within a single TCP connection.

With these binary frames, the end of the frame payload (containing e.g. the request) is specified by the Length (24) field in the frame header (RFC 7540, 4.1), which makes it unambiguous. Therefore, the HTTP request smuggling article even mentions using HTTP/2 for back-end connections as one way to prevent these vulnerabilities:

Some generic ways to prevent HTTP request smuggling vulnerabilities arising are as follows:

  • Disable reuse of back-end connections, so that each back-end request is sent over a separate network connection.
  • Use HTTP/2 for back-end connections, as this protocol prevents ambiguity about the boundaries between requests.
  • Use exactly the same web server software for the front-end and back-end servers, so that they agree about the boundaries between requests.

Does HTTP/2 prevent HTTP response splitting / CRLF injection?

HTTP response splitting is just an example of a CRLF injection. The way header block is treated (RFC 7540 4, especially 4.3) leaves less room escaping from the header block simply using two CRLFs:

Each header block is processed as a discrete unit. Header blocks MUST be transmitted as a contiguous sequence of frames, with no interleaved frames of any other type or from any other stream. The last frame in a sequence of HEADERS or CONTINUATION frames has the END_HEADERS flag set. The last frame in a sequence of PUSH_PROMISE or CONTINUATION frames has the END_HEADERS flag set. This allows a header block to be logically equivalent to a single frame.

A newline is also in general less significant as explained in Google's Introduction to HTTP/2:

Unlike the newline delimited plaintext HTTP/1.x protocol, all HTTP/2 communication is split into smaller messages and frames, each of which is encoded in binary format.

While the serialization of the header list can also help with other type of CRLF vulnerabilities like HTTP Header Injections, it doesn't automatically prevent all possible CRLF vulnerabilities in the web application, as the web application could still treat %0d%0a in GET data, POST data, cookies or in any single header specially. To prevent that, e.g. Netsparker Security Team recommends:

How to Prevent CRLF / HTTP Header Injections in Web Applications

The best prevention technique is to not use users input directly inside response headers. If that is not possible, you should always use a function to encode the CRLF special characters. Another good web application security best practise is to update your programming language to a version that does not allow CR and LF to be injected inside functions that set HTTP headers.

| improve this answer | |
  • So how can there be only one way of saying where something ends in HTTP/2? You need content-length for progress bars and transfer encoding for streaming data as it generates. Note that these are different use cases where different methods should be applied. – Joshua Jul 23 at 16:31
  • In HTTP/2 there's only a single method for all data streams, which is an exchange of binary-encoded frames. I've added some references that hopefully better explains how the request end is not specified like in these HTTP/1.1 headers, but in the length field of the frame header. – Esa Jokinen Jul 23 at 17:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.