<aside> 💡 Series:

HoL Blocking and Priority Inversion in QUIC

HoL Blocking Allows Attacks in QUIC

HoL Blocking and the Deadlock Hazard in QUIC

Relates: Head-of-Line Blocking in QUIC and HTTP/3: The Details

</aside>


Protocol designers underestimate how badly people will implement their designs.

Abstract

Compression schemes that allow head-of-line blocking are targets for memory exhaustion attacks against the decoder. Detecting such an attack is not trivial. Without guidance, programmers are likely to produce vulnerable implementations. HoL blocking must either be prohibited at the protocol level or the attack mitigation mechanism must be specified explicitly in the compression specification. One way to avoid an attack is presented.

Introduction

In the previous article, we discussed how head-of-line blocking can cause priority inversion and vice versa. In the second part of the series, we will examine potential attacks made possible by head-of-line blocking.

Problem Statement

Head-of-line blocking causes the decoder to queue header blocks that cannot be decoded due to a missing dynamic entry. Under normal circumstances, this occurs because of packet loss or reordering. An adversary, however, may create this scenario artificially in order to get the decoder to queue data, thereby creating a denial-of-service attack.

<aside> 📘 QPACK Blocked Stream

QUIC 的 sender 和 receiver 会维护一个 dynamic header table,用来 encoder/decoder compressed header(QPACK)。如果一个低优先级的 stream 更新了这个 table,而高优先级的 stream 依赖于这个更新,那么低优先级的 stream 就可能把高优先级的 stream 给 HoLB 了。

RFC 9204 - QPACK: Field Compression for HTTP/3

header table 的更新会维护一个 Insert Count,encoder 编码时会设置 Required Insert Count 告知 decoder,所以会出现下文中的,一个 stream 的解码依赖于另一个 stream 的 update。

</aside>

Here, a simple recommendation that the decoder use a timer is insufficient. The decoder must decide how much data it is willing to buffer and for how long. In other words, it must be able to differentiate between an attack and a regular packet loss/reordering situation. An incorrect determination may mean allowing a server to be DoSed; err the other way, and a valid connection is aborted.

Sample Attack

The attacker’s strategy is simple: send header blocks that contain a reference to a non-existent dynamic entry:

The decoder cannot resolve a reference and has to wait — buffering data. More and more header block data is sent. To maximize the effect of the attack, the adversary may use more than one — potentially all — available streams.

Mitigation Strategies

Strategy 1: Simple Timer

The decoder may associate a simple timer with each stalled header block. A simple timer has to be quite conservative in order to eliminate false positives. During that time, the attacker writes more data to each of the header blocks in a round-robin fashion, perhaps even resolving the blocking entry to reset the decoder timer while introducing a new unresolved entry at the same time. The amount of data queued at the decoder grows and grows and the server is eventually hosed.

Strategy 2: Adaptive Timer