The commonly used “net” library in Go and Rust languages is also impacted by the mixed-format IP address validation vulnerability.
The bug has to do with how net treats IP addresses as decimal, even when they are provided in a mixed (octal-decimal) format.
Consequently, applications relying on net could be vulnerable to indeterminate Server-Side Request Forgery (SSRF) and Remote File Inclusion (RFI) vulnerabilities.
Previously, the flaw impacted various implementations of the netmask library, relied on by thousands of applications.
Later on, the Python standard library called ipaddress was also found to be vulnerable to the flaw.
The vulnerability, tracked by CVE-2021-29922 (for Rust) and CVE-2021-29923 (for Golang) concerns how net handles mixed-format IP addresses, or more specifically when a decimal IPv4 address contains a leading zero.
A simple search for “import net” on GitHub reveals over 4 million files for Go alone relying on the net library.
An IP address can be represented in a variety of formats, including hexadecimal and integer, although most commonly seen IPv4 addresses are expressed in the decimal format.
For example, BleepingComputer’s IPv4 address represented in decimal format is 104.20.59.209, but the same can be expressed in the octal format as, 0150.0024.0073.0321.
Say you are given an IP address in decimal format, 127.0.0.1, which is widely understood as the local loopback address or localhost.
If you were to prefix a 0 to it, should an application still parse 0127.0.0.1 as 127.0.0.1 or something else?
Try this in your web browser. In tests by BleepingComputer, typing 0127.0.0.1/ in Chrome’s address bar has the browser treating it as an IP in octal format.
On pressing enter or return, the IP in fact changes to its decimal equivalent of 87.0.0.1, which is how most applications are supposed to handle such ambiguous IP addresses.
Of particular note is the fact, 127.0.0.1 is not a public IP address but a loopback address, however, its ambiguous representation changes it to a public IP address leading to a different host altogether.
But, in the case of the net library, any leading zeros would simply be stripped and discarded.
According to IETF’s original specification, parts of an IPv4 address can be interpreted as octal if prefixed with a “0.”
But the net module in both Go and Rust ignores this and considers parts as being decimal, as shown in the researchers’ reports [1, 2].
Consequently, if a developer was using net to validate if an IP address belongs to a certain range (e.g. parsing a list of IPs against an access control list (ACL)), the result may come out wrong for octal-based representations of IPv4 addresses.
This can cause indeterminate Server-Side Request Forgery (SSRF) and Remote File Inclusion (RFI) vulnerabilities in applications.
Multiple applications and languages impacted
Go and Rust aren’t the only languages to be impacted by this bug.
This mixed-format IP address validation bug had previously impacted Python’s ipaddress library (CVE-2021-29921), netmask implementations (CVE-2021-28918, CVE-2021-29418), and similar libraries.
In most cases, the bug has been rated as having a High or Critical severity:
According to the project maintainers, Golang’s net module would have a patch [1, 2] issued in (beta) version 1.17.
Sick Codes shared some insights with BleepingComputer, including that the patch was also accepted by Kubernetes maintainers:
“The Go vulnerability is slightly less impactful than rust as it only deals with CIDR blocks.”
“However, it was important enough for Kubernetes to cherry-pick the fix.”
“All in all, since they were standard library changes that would affect all projects written in the language themselves, they needed a lot of testing or for the patches to be made redundant,” Sick Codes told BleepingComputer in an email interview.
For Rust, a fix has already been merged in the net library, as confirmed by BleepingComputer:
Rust language users should be using version 1.53.0 or above that contains the mitigations for this vulnerability.