quic-go is a popular implementation of the QUIC protocol in the Go programming language. It is used by various applications and projects to establish fast, secure, and reliable connections over the internet. However, a recent vulnerability (CVE-2024-53259) in quic-go versions prior to .48.2 allowed off-path attackers to disrupt the communication between clients and servers by injecting specially crafted ICMP Packet Too Large packets.

This blog post provides an overview of the vulnerability, a detailed explanation of the exploit, code snippets demonstrating the issue, and links to relevant documentation and patches.

Understanding the vulnerability

The vulnerability occurred due to how quic-go versions before .48.2 handled ICMP Packet Too Large packets. When such a packet was received, the affected quic-go versions would reduce the Maximum Transmission Unit (MTU) to the value specified in the ICMP packet. Since the affected quic-go versions used IP_PMTUDISC_DO, the kernel would then return a "message too large" error on sendmsg when quic-go tried to send a packet that exceeded the falsely claimed MTU.

By setting the false MTU value to smaller than 120 bytes (the minimum MTU for QUIC), an attacker could disrupt a QUIC connection. Crucially, this could be done even after the handshake was completed, which means that the attacker could bypass any TCP fallback that might be implemented at the application layer (e.g., browsers falling back to HTTP over TCP if they're unable to establish a QUIC connection).

To mount an attack, the attacker needs to know at least the client's IP and port tuple.

Code snippet demonstrating the vulnerability

In the vulnerable versions of quic-go, the following code snippet shows how the ICMP Packet Too Large packets were handled:

func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
    n, addr, err = c.PacketConn.ReadFrom(p)
    if err != nil {
        return n, nil, err
    }
    if c.pmtud.IP_MTU ==  {
        return n, addr, err
    }
    // Get the current MTU and base the minimum MTU on that value
    mtu := c.pmtud.IP_MTU
    minMTU := mtu - 120 + 68
    // Check if the received packet violates the minimum MTU
    if n < minMTU {
        return , nil, &errTooSmall{}
    }
    return n, addr, err
}

An off-path attacker could create a specially crafted ICMP Packet Too Large packet with a false MTU value smaller than 120 bytes, which would then cause the connection to be disrupted.

- CVE-2024-53259 - Vulnerability Details
- GitHub - quic-go v.48.2 Release Notes
- GitHub - quic-go Commit Fixing the Vulnerability

Exploit details

There is no widely available exploit code for this vulnerability. However, an attempt to create a proof-of-concept exploit might include the following steps:

Create a custom ICMP Packet Too Large packet with an MTU value smaller than 120 bytes.

2. Send the specially crafted packet to a victim client's IP and port tuple that is using a vulnerable quic-go version.
3. Observe the injection of the false MTU value and its consequences, such as the disruption of the QUIC connection and potential bypassing of application-layer fallbacks.

Conclusion

The quic-go vulnerability (CVE-2024-53259) allowed off-path attackers to disrupt QUIC connections by injecting false ICMP Packet Too Large packets, potentially bypassing fallback mechanisms at the application layer. This vulnerability has been fixed in quic-go version .48.2, and users are encouraged to update their systems to ensure that they are protected against this attack.

Timeline

Published on: 12/02/2024 17:15:12 UTC