All swift-nio-http2 users, please update to swift-nio-http2 version 1.5.0 urgently.
A number of HTTP/2 server implementations have been discovered to be at risk of a number of different denial of service attacks. SwiftNIO HTTP/2 has been affected by several of these vulnerabilities. This disclosure covers all of them.
All SwiftNIO HTTP/2 versions between 1.0.0 and 1.4.0 inclusive are affected.
SwiftNIO HTTP/2 is affected by:
CVE-2019-9512: Ping Flood
CVE-2019-9514: Reset Flood
CVE-2019-9515: Settings Flood
CVE-2019-9516: 0-length headers memory leak
CVE-2019-9518: Empty DATA frame flooding
Ping Flood, Reset Flood, Settings Flood (CVE-2019-9512, CVE-2019-9514, CVE-2019-9515)
A SwiftNIO HTTP/2 server can be forced to buffer unbounded amounts of memory when flooded with control frames that require an automatic response. This occurs because SwiftNIO HTTP/2 will automatically write the response frame and send it down the
Channel without checking whether the
Channel is actually capable of sending the data. If the remote peer is not reading from the
Channel, then the
Channel will be forced to buffer these frames indefinitely. Done for a sufficiently long time this will lead to memory exhaustion and a process exit.
This attack is addressed by forcing control frames to be buffered inside the
NIOHTTP2Handler. This allows us to keep track of the number of buffered control frames we have, and ensures that we can limit the number of outstanding frames, and drop the connection if that number exceeds a configured value.
0-length HEADERS leak (CVE-2019-9516)
A SwiftNIO HTTP/2 server had a number of vectors in which it would fail to validate the amount of resources it would grant the remote peer for decoding HPACK-encoded header blocks.
In the first instance, while SwiftNIO HTTP/2 advertised a maximum decoded header list size to peers, that size was never actually enforced. A remote peer could therefore get a SwiftNIO HTTP/2 server to consume an infinite amount of memory by sending a continuous stream of HEADERS/CONTINUATION frames. This was fixed by correctly enforcing the set value of
In addition, SwiftNIO HTTP/2 was enhanced to forbid header fields with empty field names. As empty field names are forbidden by the HTTP RFCs, there is no reason to accept them here, and they are likely a symptom of an attempted denial of service attack.
Empty DATA frame flooding (CVE-2019-9518)
A SwiftNIO HTTP/2 server could be forced to consume substantial CPU resources by sending it an unbounded sequence of empty DATA frames that do not have END_STREAM set on them. These frames would not cause state transitions and would not be rate limited, so they could not easily be rejected automatically.
This attack was mitigated by adding heuristics that prevent sequences of empty DATA frames without END_STREAM set. Receiving multiple empty DATA frames in sequence will now cause connection teardown.