Full Report
needrestart is a tool that probes the system to see if a system or service needs to be restarted. It's called when using apt-get upgrade when a shared library does not exist on the system anyone. The authors of this post for 3 LPEs in the application that runs as root. To determine whether a Python process needs to be restarted, needrestart extracts the PYTHONPATH variable from the process before executing a pre-loaded script. Since an attacker can set the variable and the process uses the interpreter, we can put our binary at this path and execute it as root. The same issue also exists in Ruby as well. To determine whether a process is Python or not, it checks the processes /proc/pid/exe file then matches it against a regular expression. A previous vulnerability existed on this that the regex was not anchored at the beginning and end. They realized that there is a time of check vs. time of use (TOCTOU) issue that allows for the verification to read one path but then the execution to use another by switching it out. Both Python and Ruby were vulnerable to this attack. In Perl, the functionality was different than the other two. Instead, it calls into scan_deps to analyze a Perl script but reads its source files recursively. Unfortunately, it feel victim to a super bad pitfall in Perl: insecure usage of file operations. In Perl, open() will execute bash commands if there's a pipe (|) inside of it. By passing in /home/jane/perl| as the file name to read, the bash script gets run. Crazy! After finding the insecure usage of open, there were several eval() calls vulnerable to code injection vulnerabilities as well. It's interesting how these vulns got through - many of them are fairly simple issues that I thought had died out years ago. I love the Qualys posts. Straight to the point on the vulnerability with zero fluff. They keep finding really bad vulnerabilities in things on Ubuntu. On the Day Zero Podcast, they mentioned that the easiest way was the Kernel for a long time. Since that has been hardened, people have started looking elsewhere such as the userland apps that run as Root.
Analysis Summary
# Vulnerability: Multiple Local Privilege Escalations in needrestart
## CVE Details
- **CVE ID:** CVE-2024-48990, CVE-2024-48992, CVE-2024-48991, CVE-2024-10224, CVE-2024-11003
- **CVSS Score:** 7.8 (High) - *Typical for LPE via local vectors*
- **CWE:** CWE-426 (Untrusted Search Path), CWE-367 (TOCTOU), CWE-78 (OS Command Injection), CWE-94 (Code Injection)
## Affected Systems
- **Products:** needrestart (installed by default on Ubuntu Server since 21.04)
- **Versions:** 0.8 through versions prior to 3.8
- **Configurations:** Systems where `interpscan` is enabled (default configuration).
## Vulnerability Description
Multiple flaws were discovered in how `needrestart` (running as root) scans interpreted processes (Python, Ruby, Perl) to determine if they require a restart:
1. **Environment Variable Injection (CVE-2024-48990/CVE-2024-48992):** For Python and Ruby processes, `needrestart` extracts the `PYTHONPATH` or `RUBYLIB` from an unprivileged process and applies it to its own root-level execution of the interpreter, leading to arbitrary code execution as root via malicious libraries.
2. **Race Condition/TOCTOU (CVE-2024-48991):** A "Time-of-Check to Time-of-Use" flaw exists where `needrestart` verifies a process's executable path via `/proc/pid/exe` but can be tricked into executing a relative attacker-controlled binary (e.g., a fake `python` binary) by changing the working directory or pathing between the check and the execution.
3. **Perl Command Injection (CVE-2024-10224/CVE-2024-11003):** The Perl scanner used `Module::ScanDeps`, which utilized an insecure `open()` call that interprets filenames ending with a pipe (`|`) as shell commands. An attacker can craft a filename like `/home/user/perl|` to execute arbitrary bash commands when scanned.
## Exploitation
- **Status:** PoC created by Qualys; vulnerabilities are considered "trivially exploitable."
- **Complexity:** Low
- **Attack Vector:** Local (Requires existing shell access on the system).
## Impact
- **Confidentiality:** High (Full system access)
- **Integrity:** High (Full system access)
- **Availability:** High (Ability to crash or disable services)
## Remediation
### Patches
- **needrestart:** Update to version 3.8 or higher.
- **Ubuntu/Debian:** Apply security updates via `apt-get update && apt-get upgrade`.
- **Module::ScanDeps:** Update to version 1.37 or higher (fixes the insecure `open()` call).
### Workarounds
Disable the interpreter scanning feature in the `needrestart` configuration file:
1. Edit `/etc/needrestart/needrestart.conf`.
2. Set `$nrconf{interpscan} = 0;`.
## Detection
- **Indicators of Compromise:** Unusual child processes of `needrestart` (e.g., shells or network connections spawning from Python/Ruby/Perl processes running as root).
- **Audit Logs:** Monitor `auth.log` or `syslog` for `needrestart` activity followed by unexpected privilege escalations.
## References
- **Qualys Security Advisory:** hxxps[://]www[.]qualys[.]com/2024/11/19/needrestart/
- **Ubuntu Security:*** hxxps[://]ubuntu[.]com/security/notices/USN-7115-1
- **GitHub Repository:** hxxps[://]github[.]com/liske/needrestart