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.
Leading zero changes the IP address
This week, at DEF CON, security researchers Cheng Xu, Victor Viale, Sick Codes, Nick Sahler, Kelly Kaoudis, opennota, and John Jackson have disclosed a flaw in the net module of Go and Rust languages.
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 an IETF draft (which expired before it could be formalized into a specification), parts of an IPv4 address can be interpreted as octal if prefixed with a "0."
As such, rules around how a mixed-format IPv4 address should be parsed vary between applications.
The net module in both Go and Rust, for example, considers all octets of an IPv4 address as 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.
Source: Sick.Codes
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:
[RELEASE] https://t.co/8GxarINC1c
— Sick.Codes (@sickcodes) August 7, 2021
CVE-2020-28360 9.8
CVE-2021-28918 9.1
CVE-2021-29418 5.3
CVE-2021-29921 9.8
CVE-2021-29662 7.5
CVE-2021-29424 7.5
CVE-2021-29922 NEW
CVE-2021-29923 NEW
Oracle S1446698 NEW
Advisories tonight
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:
"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.
Update 12:30 PM ET: Clarified the linked IETF draft had expired and as such never formalized.
**Correction, Aug 8th, 02:10 AM ET: Kubernetes did not implement the fix but reverted it instead, to prevent breaking any builds unexpectedly.
Comments
TsofT - 2 years ago
Heh, "safe" and "better" languages taking it on the chin. Ouch!