Skip to main content

7. Security Considerations

This section describes potential areas of security concern with HPACK:

  • Use of compression as a length-based oracle for verifying guesses about secrets that are compressed into a shared compression context.

  • Denial of service resulting from exhausting processing or memory capacity at a decoder.

7.1. Probing Dynamic Table State

HPACK reduces the length of header field encodings by exploiting the redundancy inherent in protocols like HTTP. The ultimate goal of this is to reduce the amount of data that is required to send HTTP requests or responses.

The compression context used to encode header fields can be probed by an attacker who can both define header fields to be encoded and transmitted and observe the length of those fields once they are encoded. When an attacker can do both, they can adaptively modify requests in order to confirm guesses about the dynamic table state. If a guess is compressed into a shorter length, the attacker can observe the encoded length and infer that the guess was correct.

This is possible even over the Transport Layer Security (TLS) protocol (see [TLS12]), because while TLS provides confidentiality protection for content, it only provides a limited amount of protection for the length of that content.

Note: Padding schemes only provide limited protection against an attacker with these capabilities, potentially only forcing an increased number of guesses to learn the length associated with a given guess. Padding schemes also work directly against compression by increasing the number of bits that are transmitted.

Attacks like CRIME [CRIME] demonstrated the existence of these general attacker capabilities. The specific attack exploited the fact that DEFLATE [DEFLATE] removes redundancy based on prefix matching. This permitted the attacker to confirm guesses a character at a time, reducing an exponential-time attack into a linear-time attack.

7.1.1. Applicability to HPACK and HTTP

HPACK mitigates but does not completely prevent attacks modeled on CRIME [CRIME] by forcing a guess to match an entire header field value rather than individual characters. Attackers can only learn whether a guess is correct or not, so they are reduced to brute-force guesses for the header field values.

The viability of recovering specific header field values therefore depends on the entropy of values. As a result, values with high entropy are unlikely to be recovered successfully. However, values with low entropy remain vulnerable.

Attacks of this nature are possible any time that two mutually distrustful entities control requests or responses that are placed onto a single HTTP/2 connection. If the shared HPACK compressor permits one entity to add entries to the dynamic table and the other to access those entries, then the state of the table can be learned.

Having requests or responses from mutually distrustful entities occurs when an intermediary either:

  • sends requests from multiple clients on a single connection toward an origin server, or

  • takes responses from multiple origin servers and places those on a shared connection toward a client.

Web browsers also need to assume that requests made on the same connection by different web origins (see [ORIGIN]) are made by mutually distrustful entities.

7.1.2. Mitigation

Users of HPACK can take steps to limit the potential for dynamic table probing by restricting the ability of mutually distrustful entities to add entries to the dynamic table and observe the state of the dynamic table.

The most effective mitigation is to avoid sharing connections or compression contexts between requests or responses that are not a result of actions from the same origin.

For intermediaries, this means that requests from different clients and responses from different origin servers MUST NOT share a single HPACK compression context.

For user agents, this means that compression contexts MUST be separated for requests to different origins that are not known to be under common control.

7.1.3. Never-Indexed Literals

Implementations can also choose to protect sensitive header fields by not compressing them and instead encoding their value as literals.

Refusing to generate an indexed representation for a header field is only effective if compression is avoided on all hops. The never-indexed literal bit (see Section 6.2.3) can be used to signal to intermediaries that a particular value was intentionally sent as a literal.

An intermediary MUST NOT re-encode a header field that uses the never-indexed literal representation with another representation that would index it. If HPACK is used for re-encoding, a literal representation without indexing (see Section 6.2.2) can be used instead.

The choice to use a never-indexed literal representation for a header field depends on several factors. Since HPACK does not protect against guessing an entire header field value, short or low-entropy values are more readily recovered by an adversary. Therefore, an encoder might choose not to index values with low entropy.

An encoder might also choose not to index values for header fields that are considered to be highly valuable or sensitive to recovery, such as the Cookie or Authorization header fields.

7.2. Static Huffman Encoding

There is no currently known attack against a static Huffman encoding. A study has shown that using a static Huffman encoding table created an information leakage; however, this same study concluded that an attacker could not take advantage of this information leakage to recover any meaningful amount of information (see [PETAL]).

7.3. Memory Consumption

An attacker can try to cause an endpoint to exhaust its memory. HPACK is designed to limit both the peak and stable amounts of memory allocated by an endpoint.

The amount of memory used by the compression context can be limited by setting a maximum size for the dynamic table. In HTTP/2, this is controlled by the SETTINGS_HEADER_TABLE_SIZE setting (see Section 6.5.2 of [HTTP2]).

An encoder can limit the amount of state that can be created at a decoder by controlling the dynamic table size. In HTTP/2, this is reported by the decoder through the use of the SETTINGS_HEADER_TABLE_SIZE setting. An encoder MUST limit the dynamic table size to the value reported by the decoder, thereby controlling the amount of memory that is committed.

A decoder can limit the amount of memory committed to the dynamic table by signaling a lower SETTINGS_HEADER_TABLE_SIZE value than the default. In HTTP/2, the default value is 4,096 octets, which means that the encoder can use up to this amount of memory for the dynamic table unless the decoder changes this by sending a SETTINGS_HEADER_TABLE_SIZE setting in a SETTINGS frame.

7.4. Implementation Limits

An implementation has to set a limit for the values it accepts for integers and for the size of string literals. In the same way, it has to set a limit to the number of entries it will store in the dynamic table. Not setting a limit could expose an implementation to attacks, similar to what has been observed in protocol implementations that did not set reasonable limits.