Recently, Qualys discovered and reported a critical vulnerability affecting the popular GLIBC ecosystem, which is installed by default on most Linux-based operating systems. Specifically, a buffer overflow was found in the code responsible for handling special environment variables during the startup of a process which can result in a local privilege escalation. Fortunately, exploitation of this vulnerability can be detected by Falco. In this article, we will deep dive into this vulnerability, dubbed ‘Looney Tunables’, to see why it happened and how to detect and mitigate the risk using Falco rules.
The flaw, assigned CVE-2023-4911 with a score of 7.8, is considered a high severity vulnerability. If exploited, the attacker could gain root permission on a Linux installation with GLIBC version 2.34 (see Linux distribution for accurate information on status). At the time of this writing, several proof of concept versions of the exploit have been released. The exploitation itself is straightforward; even with memory address brute forcing involved, successful exploitation could happen in under five minutes.
An attacker begins by modifying the LD_LIBRARY_PATH for a given suid binary or making a copy, allowing processes to load untrusted shared objects from an attacker-controlled directory. This results in the execution of malicious code with root privileges.
Fixes for this vulnerability are currently being released by the various Linux distributions. We recommend you check their sites for fix information, as this vulnerability is affecting many different versions.
GLIBC is installed by default on many popular Linux distributions, such as Ubuntu, Fedora, Red Hat, and Debian. It includes the Linux dynamic loader (ld.so), a piece of software responsible for loading all the needed shared objects for a program to run. Its task can be briefly described as:
- Loading shared libraries
- Symbol resolution
- Performing relocations
- Mapping the binary in memory
- Memory management
- Running the binary
The vulnerability found by Qualys happens during the initialization of the dynamic linker, specifically the handling of the GLIBC_TUNABLES environment variable. This variable allows for tweaking GLIBC behavior during the subsequent events.
A list of available tunables can be obtained by running the following command:
The tunables must be provided to the target binary as a list of colon-separated key-value pairs during the program execution. The linker is responsible for parsing, and eventually stripping, security sensitive tunables from the environment variables. Below is the in-depth analysis of what happens during tunables parsing and exploitation.
The flaw was introduced with commit 2ed18c (“Fix
SXID_ERASE behavior in setuid programs (BZ #27471)”) inside
__tunables_init function. When this function is called, it loops through environment variables and searches for GLIBC_TUNABLES. Once found, it calls
tunables_strdup to create a copy of the variable and start to process it. Since GLIBC is not yet initialized, the strdup function uses
__minimal_malloc under the hood, which calls mmap to request memory from the Kernel. This causes the memory to be allocated from virtual memory instead of the heap.
The buffer overflow occurs because of the way the arguments are parsed. If the tunable string is in the format of tunable1=tunable2=value, it will first parse the string as tunable1=”tunable2=value” and later keep processing it as tunable2=value. This will lead to more data being copied inside the allocated buffer than is allowed. Although the vulnerability was discovered by source code auditing, Qualys stated that fuzzing the logic with AFL++ or Libfuzzer was able to reproduce the crash in seconds.
The exploitation technique explained by Qualys is straightforward and consists of filling the environment with NULL bytes until we overflow into the
l_info member of
link_map structure. This structure
(Elf64_Dyn) points to the dynamic section of the binary and is composed of a tag and a value. In this case, we are interested in the
DT_RPATH tag, which is the dynamic section of the binary containing the location where the library lookup is performed.
Carefully crafting a payload which modifies that pointer could lead to the binary loading shared objects from untrusted directories, and that’s a major issue when it comes to setuid binaries.
The current exploitation techniques won’t bypass ASLR and are based on brute-force guessing. Considering the stack is allocated 16GB of memory, the process environment can occupy up to 6MB, and the chosen pointer points exactly in the middle of the stack, there’s a good chance that the pointer will be valid after 2,730 tries. In a loop on a host, this takes mere minutes.
Falco, a cloud-native security tool based on system calls, can be used to detect the exploitation in the runtime of the Looney Tunables vulnerability.
To reach the vulnerable code, an exploit has to pass data through a particular environment variable GLIBC_TUNABLES, which can be observed by Falco. To decrease the risk of false positives, Falco can also look for a segmentation fault signal when the process crashes. As previously mentioned, the exploit brute forces its way to the proper memory address, so any failure will result in a segmentation fault (a.k.a. crash).
The best way to mitigate this vulnerability is through patching. However, some additional solutions do exist but will vary between vendors. If you are affected by this CVE-2023-4911, you should patch your system based on your affected distribution.
RedHat published instructions for using their SystemTap tools to detect which binaries are invoking GLIBC_TUNABLES in the environment and terminate them immediately. This solution may require the installation of additional software and repeat the process when the system is restarted.
The Looney Tunables vulnerability is very serious due to how many Linux distributions are involved and the relative ease of exploitation. If an attacker gains unprivileged access to a system, either through logging in as a normal user or another remote exploit, they can leverage this vulnerability to obtain root privileges. Most Linux distributions come with some form of GLIBC, so it is critical to check if you are vulnerable.
Detection can be accomplished with runtime tools, such as Falco, using rules similar to the one provided above. Since there are currently not many ways to mitigate, patching the vulnerability should be a top priority. This vulnerability will affect not just your standard Linux server, but also containers, appliances, and IoT devices. Anywhere Linux is, this vulnerability may be present.