$ nmap -p- --min-rate 5000 10.129.95.185
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-06 11:41 EDT
Nmap scan report for 10.129.95.185
Host is up (0.0072s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
File Storage
Port 80 had a login page to some kind of file manager:
This wasn't vulnerable to SQL Injection or anything. I tried visiting index.php, but was redirected back to the login.php. When the traffic is inspectedi nBurp, I noticed that index.php was still loaded.
This means that we can view the pages without logging in since they are loaded before we are redirected. When I used Burp's Match and Replace function to change the 302 Found to 200 OK, I could load the page normally:
Within the Accounts tab, we can add a user.
So I created one and we can remove the Burpsuite filtering. Within the Files tab, there's a backup of the entire site uploaded.
We can download this file and analyse the source code back on my machine. Here's the logs.php.
<?php
session_start();
if (!isset($_SESSION['user'])) {
header('Location: login.php');
exit;
}
?>
<?php
if (!$_SERVER['REQUEST_METHOD'] == 'POST') {
header('Location: login.php');
exit;
}
/////////////////////////////////////////////////////////////////////////////////////
//I tried really hard to parse the log delims in PHP, but python was SO MUCH EASIER//
/////////////////////////////////////////////////////////////////////////////////////
$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;
$filepath = "/var/www/out.log";
$filename = "out.log";
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
ob_clean(); // Discard data in the output buffer
flush(); // Flush system headers
readfile($filepath);
die();
} else {
http_response_code(404);
die();
}
?>
It seems that there's an exec function used, and the delim parameter is not sanitised when being passed in, thus creating a command injection vulnerability. We can send this request to confirm we have RCE.
m4lwhere@previse:/var/www/html$ sudo -l
[sudo] password for m4lwhere:
User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh
Here's the script:
#!/bin/bash
# We always make sure to store logs, we take security SERIOUSLY here
# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time
gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz
This script was running gzip without the full path, so we can do some PATH injection. Create a script called gzip that makes /bin/bash an SUID binary via chmod u+s /bin/bash, then make it executable.
Afterwards, change the PATH variable to include /tmp first and run the script as root.