• Donald Ashdown

Hack the Box - Previse

Updated: Apr 20

Engagement flow


This was a really cool machine that started off with web enumeration, leading to a login bypass in which we had to submit a request with custom parameters to satisfy a hidden registration form, and intercept not the request, but the response. From here we performed code review and identified an OS command injection vulnerability that we exploited for access as user www-data. From here we connected to the MySQL server with previously found credentials, dumped the password table, cracked the password and elevated to user.

We pursued privilege escalation to root via a sudo misconfiguration and created a custom environment variable to perform insecure path injection of a backup script to root.

  • Request proxying

  • Response intercepting

  • Content discovery

  • Code review

  • Login bypass

  • OS cmd injection

  • MySQL enumeration

  • Relative path injection

Tools used
  • Dirbuster

  • Burpsuite

  • Burp repeater

  • Linpeas

  • MySQL

  • Hashcat


Starting as always we perform an nmap scan and identify a very narrow attack surface with only 2 ports open. In the background I set autorecon to start running to perform more in-depth enumeration incase I missed anything.

Port 22 - SSH, likely used for lateral movement

Port 80 - HTTP, likely used for initial foothold

Starting Nmap 7.91 ( https://nmap.org ) at 2021-12-26 12:58 EST
Nmap scan report for
Host is up (0.086s latency).
Not shown: 998 closed ports
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: 
|   /: 
|_      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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.14 seconds

Web Enumeration

Reviewing the website it looks pretty basic as we arrive at a landing page asking us to login.

Starting dirbuster in the background, starts to reveal our next move on the playing field as we see several php pages all with 302 redirects. This immediately suggests we must leverage a proxy to burp the port and somehow tamper with these redirects.

302 redirect bypassing

Here we are working with the login page, investigating ways we can perhaps tamper or bypass not only the login page but the 302 redirect for all the additional php pages found earlier. It could be the case where intercepting those requests and denying the redirect, provides us with valuable information that the developer did not intend, or did not want us having access to.

We start off by intercepting several of the pages, and eventually arrive to the accounts.php page. Reviewing this page before it hits the redirect actually reveals the options on the page, which allow for account creation. From here we view the rendered page and confirm these findings in the images below.

In this image we see the rendered version of accounts.php and confirm we can indeed create an account here.

Login bypass

From this point, our goal is to gain access by registering an account for the webpage. We know and understand that the accounts.php page allows us to create an account so we attempt to get fancy and create an account through submitting the form parameters in a POST request.

Below we have taken a GET request to accounts.php and change the GET parameter to a POST parameter. Below this, we attempt to add the form field ID's to create an account that we identified earlier in the accounts.php intercept, before the redirect.

Upon submitting, this did not work and the response would show 302. So I eventually learned, after many questions and much research that we could actually burp the response page. This was mind blowing as I had never encountered this before.

The response page was initially 302 (redirect) which we already know, so we could change this by right clicking on burpsuite under the initial proxy tab and select "Do Intercept the Response".

We intercept the response and change the 302 not found to 200. This worked at times and created our account, but other times it did not.

Alternative login bypass

Alternatively you can simply intercept the response page, forward this page as rendered and have access to create a user through the GUI, which worked in those situations where sending the manual parameters through burp did not work.

Initial foothold

Upon registering our account and gaining access we poke around and eventually under the "files" tab, we find the sitebackup.zip

Investigating backup.zip / code review

Download and unziping the backup.zip provides the following results.

We start by looking at config.php and immediately find some mySQL credentials.

We do not have access to the mysql service at this time as it must be internal so we will store these in our back pocket for later.

└─$ cat config.php       


function connectDB(){
    $host = 'localhost';
    $user = 'root';
    $passwd = 'mySQL_p@ssw0rd!:)';
    $db = 'previse';
    $mycon = new mysqli($host, $user, $passwd, $db);
    return $mycon;


We eventually come across the logs.php file where we find a vulnerability which is highlighted in red below. What we see is a variable being taken from the webpage, provided by the user and passed directly to python exec function in the backend. This is very dangerous as user input sanitization is not present which means we can append escape characters and enter custom commands to be passed to the "exec" backend function. We will need to find where exactly the web page is requesting this POST - Delim argument in order to enumerate this for a vulnerability

└─$ cat logs.php



if (!isset($_SESSION['user'])) {

header('Location: login.php');






header('Location: login.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;

$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



} else {




We find the delim variable under the "management menu" >> log data.

So we simply use burp to proxy the request and hit submit.

Viewing the intercept request indeed provides us with the delim variable. We try the classic string terminator character and in order to test, we will try the ping command to a tcp dump listener back on our local machine.

Great this totally worked! Next we will try to execute a reverse shell.

Our listener successfully catches the callback and provides us our shell as user www-data.

MYSQL enumeration

Our first step on this machine is to try our SQL credentials to confirm if A we are running SQL and B, if we can actually access it which we can!

From here our next move is to show the databases and tables in which we find a hash for the m4lwhere user.

Determine the hash?

We already know what the hash type is, as we found this in login.php when we originally downloaded and reviewed the site backup files. We noticed that php is calling the crypt function.

We can also identify this hash with Johnny, the gui version of the john the ripper.

So we can crack this in hashcat.


Great we can ssh in as user m4lwhere.


For this root phase, I did not even need to upload an enumeration script. I always check sudo permissions for the individual user and in this instance we find our next path.

We head over to the /opt/scripts/access_backup.sh file where we can see the sudo file inwhich we have permissions to run. Looking at this file we don't have permissions to modify so we won't be editing and injecting any code into this script. No specific libraries are called that we could modify. All paths are absolute so there will be no path injection. We do eventually clue in that the binary "gzip" does not have an absolute path and this is our target for exploitation to privilege escalation.

So taking a look at our environment variable we see nothing out of the ordinary. But what we can do is create a new environment variable that holds the tmp directory where can create a malicious file called gzip. We enter a bash reverse shell and execute as root! Happy days :)

18 views0 comments