CVE-2024-24790 - Breaking Down the IPv4-Mapped IPv6 Address Validation Bug in Go
*CVE-2024-24790* is a vulnerability found in Go's standard library networking package—specifically the net package. It affects the way Go recognizes IPv4-mapped IPv6 addresses for different "IsX" methods like IsPrivate, IsLoopback, IsMulticast, and others.
If your server or application checks if an IP is private, loopback, or multicast, this bug might make your code believe an IPv4 address coming through IPv6 is not private or loopback, even when it really is. This misclassification might lead to security slips—think leaking admin panels, allowing unwanted access, or failing to limit network exposure.
Quick Recap: What's an IPv4-mapped IPv6 Address?
IPv4-mapped IPv6 addresses look like this: ::ffff:192.168..1. They allow IPv4 addresses to be represented as IPv6 addresses, making the transition between IPv4 and IPv6 a bit easier.
In Go, you might expect that calling methods like IsPrivate() or IsLoopback() would work the same for both "192.168..1" and "::ffff:192.168..1". But they didn't.
Try this code with a vulnerable version of Go (pre-1.22.4 or pre-1.21.11)
package main
import (
"fmt"
"net"
)
func main() {
ip1 := net.ParseIP("192.168.1.123")
ip2 := net.ParseIP("::ffff:192.168.1.123")
fmt.Println(ip1, "IsPrivate?", ip1.IsPrivate()) // true
fmt.Println(ip2, "IsPrivate?", ip2.IsPrivate()) // false, but should be true!
fmt.Println(ip2, "IsLoopback?", ip2.IsLoopback()) // false for loopback v4 too!
}
Expected output
192.168.1.123 IsPrivate? true
::ffff:192.168.1.123 IsPrivate? false
::ffff:192.168.1.123 IsLoopback? false
Both checks on the IPv4-mapped address (::ffff:192.168.1.123) should return true but they don't.
Why Does This Matter?
If you wrote a firewall, a proxy, or a web server access control using Go, and you checked incoming IPs for IsPrivate() or IsLoopback() to decide who gets through, traffic sent as IPv4-mapped IPv6 could have slipped past your filters. A malicious actor could send requests from a restricted private address, but encode it as an IPv6-mapped address and bypass your security, getting access to resources or admin features unintentionally exposed.
Suppose your web server restricts access to /admin to certain private network addresses
if ip := net.ParseIP(remoteIP); ip.IsPrivate() {
// Allow access
}
If the attacker sends: "192.168.1.123" → IsPrivate: true
But if they send: "::ffff:192.168.1.123" → IsPrivate: false (vulnerable Go), access denied?
Actually: If you meant to block public IPs and only allowed private, their IPv4-mapped IPv6 address would not be recognized correctly as private, leading to stricter access. But if you are using the negative check, they might sneak past.
A trickier example is if you are blocking public IPs but allowing private for sensitive endpoints:
// BAD LOGIC: Only block public, allow everything else.
if !ip.IsPrivate() {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// attacker uses ::ffff:192.168..2, gets past your "private only" filter!
Bottom line: Anything relying on these property checks could have gotten confused, leading to skipped restrictions or false negatives.
How Was It Fixed?
The Go team patched this in versions 1.22.4 and 1.21.11. Now, all the IsX functions internally check for IPv4-mapped IPv6 addresses and treat them as their IPv4 values.
Update Go:
Upgrade to Go 1.22.4 or Go 1.21.11.
return ip.IsPrivate()
}
Final Thoughts
If you use Go's IP inspection methods anywhere in your authentication, authorization, or network boundary code, check your dependencies and upgrade right away. This bug is subtle but can break your security assumptions.
Official references
- Go Issue #65719
- Go Release Notes
- CVE Database Entry
Patch your Go runtime now!
Stay safe and keep your Go environments up to date!
Timeline
Published on: 06/05/2024 16:15:10 UTC
Last modified on: 06/18/2024 17:59:12 UTC