Google Fixes Severe Golang Windows RCE Vulnerability
This month Google engineers have fixed a severe remote code execution (RCE) vulnerability in the Go language (Golang).
The RCE vulnerability, CVE-2021-3115, mainly impacts Windows users of Go running the go get
command, due to the default behavior of Windows PATH lookups.
RCE from PATH lookups in untrusted directories
Recently, Japan-based security researcher RyotaK discovered a command injection vulnerability in the Golang project.
The vulnerability, tracked as CVE-2021-3115, stems from how the compile process works when a user runs the “go get” command to fetch a repository.
Generally, on Windows systems, an OS shell command ran by the user or a program causes the shell to search for the binary/executable associated with that command within the current directory first, followed by a list of directories specified in the system PATH variable.
For example, if you type netstat
in a Windows command prompt, Windows would first look around for a netstat.exe, netstat.bat, or another netstat.* executable in the current directory (see screenshot below) which would get priority and be executed.
Also Read: How a Smart Contract Audit Works and Why it is Important
Should no netstat exist in the current folder, only then would the Windows shell look for the netstat system utility, the location of which exists on the Windows %PATH% variable.
Due to security risks associated with this behavior, both the Unix shell and Windows PowerShell had earlier dropped this default behavior and began prioritizing the %PATH% variable locations over the untrusted current directory, when executing commands.
This means, running netstat in PowerShell would launch the netstat system utility and not the locally present netstat.bat since PoweShell prioritizes looking up the binary by that name in the %PATH% directories.
However, for consistency, Golang binariesimitate Unix rules on Unix systems, and Windows rules on Windows.
This means, running the following Go command would produce slightly different behaviors on Unix and Windows systems.
out, err := exec.Command("go", "version").CombinedOutput()
This Golang line is the equivalent of running the go version
OS shell command.
On Windows, a locally present go binary would get priority, whereas Unix systems would first search its $PATH variable to see if a go binary exists in one of the trusted locations.
This model of prioritizing the local, untrusted directory over PATH locations is also implemented by helper libraries and compilers included within Go, such as cgo, a utility designed to generate Go packages that call C code.
When cgo is compiling C code on Windows, eventually, the Golang executable searches for the GCCcompiler within the (untrusted) local directory first.
“When go get downloads and builds a package that contains import “C”, it runs a program called cgo to prepare the Go equivalent of the relevant C code.”
“The go command runs cgo in the directory containing the package sources,” explains Google engineer Russ Cox.
Although most of these calls happen in a safe manner, the GCC compiler is invoked by Go’s exec.Command function which, on Windows, makes it possible for Go to launch a malicious gcc.exe included by the attacker within their application sources, rather than the legitimate GCC compiler.
It may seem like this mishap could have been caught and prevented by multiple intermediary compilers and libraries that are invoked (such as cgo or gcc), but Golang project took responsibility for the bug and issued a fix.
“Today’s bug, however, was entirely our fault, not a bug or obscure feature of gcc or git.”
“The bug involves how Go and other programs find other executables, so we need to spend a little time looking at that before we can get to the details,” says Cox.
Researcher inspired by an earlier critical vulnerability
BleepingComputer reached out to RyotaK to learn more about how he had discovered this vulnerability.
It turns out, reading about a critical command injection vulnerability in Git LFS, CVE-2020-27955, is what had inspired the researcher to hunt for a similar flaw in Golang itself.
“I found this vulnerability because of CVE-2020-27955. It was a remote code execution in Git LFS, which is caused by insecure file execution.”
“While checking the technical details of [the bug], I thought like ‘Can this vulnerability be affected to official Go project?'”
“And then, I started to read repositories that belong to the golang organization. Shortly after that, I found this vulnerability with some other vulnerabilities that have the same root cause.”
“Since this vulnerability could allow the execution of arbitrary code while building the malicious code on Windows, it may affect systems that expect Go not to execute arbitrary code at build time,” RyotaK told BleepingComputer in an email interview.
For a remote attacker to exploit this vulnerability, however, a user needs to run the go get command against a malicious repository.
“It requires some interaction by the victim; they need to run ‘go get’ against the malicious repository,” the researcher further told BleepingComputer.
The Golang team at Google has fixed the vulnerability and users are advised to upgrade their instances.
Also Read: Data Centre Regulations Singapore: Does It Help To Progress?
Users can upgrade to the recently released Go versions 1.14.14 (for 1.14.x and earlier), and 1.15.7 (for users of 1.15.x) to mitigate this vulnerability.
Additionally, Google developers have also released a patch for a cryptographic flaw, CVE-2021-3114, reported by Philippe Antoine of Catena cyber in the same releases.
The upcoming Go 1.16rc1 release is also expected to include fixes for both CVE-2021-3114 and CVE-2021-3115.
Thanks to any.run for Windows VM access.
0 Comments