CVE-2024-22189 - Memory Exhaustion in quic-go via Malicious NEW_CONNECTION_ID Frames
On January 23, 2024, a critical vulnerability (CVE-2024-22189) was disclosed in quic-go, one of the most popular Go libraries implementing the QUIC protocol. Prior to version .42., quic-go could be forced out of memory by an attacker abusing the connection ID management process in the protocol.
This post will break down the vulnerability in simple terms, explore how the exploit works, show relevant code snippets, and share references and patch info.
quic-go library, any version before .42.
All servers and programs using quic-go as a dependency for QUIC protocol support (for example, web servers, reverse proxies, or any custom Go network server).
QUIC Essentials: Connection IDs
QUIC is a modern transport protocol designed to be fast and secure, using multiplexed connections, encryption, and smart transport logic. To support client IP and port changes, QUIC uses *connection IDs* (CIDs). Both endpoints can issue new IDs and signal retirement of old ones using NEW_CONNECTION_ID and RETIRE_CONNECTION_ID frames.
Trigger Many Connection ID Retirements:
The attacker sends a huge number of NEW_CONNECTION_ID frames, each one instructing the server to retire an old connection ID.
Block Outgoing Frames:
The QUIC server (using quic-go) is supposed to acknowledge each retirement with a RETIRE_CONNECTION_ID frame. But the attacker can intentionally collapse the server's congestion window (using clever packet acknowledgments and by messing with the RTT estimate), making it almost impossible for the server to actually send out those RETIRE_CONNECTION_ID frames.
Memory Buildup:
Because the server never gets a chance to "drain" the queue of retirement frames, the backlog keeps growing. Eventually, the server process runs out of memory and crashes or becomes unresponsive.
Prevent the server from sending its own frames (e.g., by careful acknowledgment abuse).
Below is a *simplified* example pseudo-code/Go snippet to demonstrate the attack logic. (You would normally need a custom QUIC client for precise frame-level attacks.)
// Pseudo-logic for flooding NEW_CONNECTION_ID frames
for i := ; i < 100000; i++ {
sendFrame(NEW_CONNECTION_ID, connectionID: randomCID(), retirePriorTo: i)
// Optionally, control ACKs to collapse congestion window
}
To fully weaponize this, you would also send selective ACKs and manipulate RTT measurements, which is advanced and requires deep protocol knowledge.*
Fix commit:
GHSA-v4fw-pv75-qc96 on GitHub Security Advisory
Patch code
The fix prevents unchecked allocation of memory for pending retirement frames, and adds handling against an attacker-specific manipulation of the congestion window.
If you use quic-go, update to v.42. or later
go get github.com/quic-go/quic-go@v.42.
> There are NO known workarounds for affected versions. Only upgrading actually protects you.
Original References
- GitHub Security Advisory: GHSA-v4fw-pv75-qc96
- CVE-2024-22189 at NVD
Summary Table
| Metric | Description |
|--------------------------|-------------------------------------------------|
| CVE ID | CVE-2024-22189 |
| Component | quic-go (Go) |
| Affected Versions | < v.42. |
| Impact | Denial of Service, Out-of-memory crash |
| Exploitability | Remote attacker, no authentication required |
| Fixed In | v.42. |
| Workarounds | None |
Conclusion
quic-go users must update urgently. This vulnerability is easy to exploit if an attacker can open a QUIC connection to your service. There is no alternative fix or setting to block it.
Upgrade today to stay secure.
Tags: #CVE202422189 #quic-go #QUIC #GoLang #DenialOfService
*This post is exclusive and written in simple terms for easy understanding. Share it with your development or operations teams to ensure all Go-based QUIC deployments are protected!*
Timeline
Published on: 04/04/2024 15:15:37 UTC
Last modified on: 04/04/2024 16:33:06 UTC