The vulnerability lies in the handling of QUIC connection ID retirement, which can lead to an infinite loop, causing a Denial of Service. The root cause is in the quiche::Connection::send function, which is responsible for creating outgoing QUIC packets.
Prior to the patch, this function used a while let Some(...) loop to get and process connection IDs that needed to be retired. It called quiche::cid::ConnectionIdentifiers::next_retire_dcid_seq() to get the next connection ID sequence number to retire. However, RFC 9000 specifies that a packet cannot contain a RETIRE_CONNECTION_ID frame that refers to the connection ID being used in that same packet's header.
An attacker could create a scenario (e.g., through path migration) where the connection ID that next_retire_dcid_seq returned was the only one available for the connection to use for sending packets. In this case, the send function would be unable to create the RETIRE_CONNECTION_ID frame. Because the connection ID was not retired, next_retire_dcid_seq would return the same ID in the next loop iteration, leading to an infinite loop as the send function would continuously try and fail to retire the same connection ID.
The patch addresses this by changing the logic. Instead of getting one ID at a time in a while loop, the send function now gets a snapshot of all connection IDs pending retirement into a HashSet and iterates over them using a for loop. This ensures that the loop runs a finite number of times, even if some connection IDs cannot be retired in that specific packet, thus preventing the infinite loop.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| quiche | rust | >= 0.15.0, < 0.24.5 | 0.24.5 |