php反序列化小结

0x00 关注函数

Command Execution exec() shell_exec() pcntl_exec() passthru() popen() system() assert() eval()

File Access file_put_contents() file_get_contents() unlink()

construct()实例化被调用 destruct()实例化对象完调用, toString() echo一个对象被调用 wakeup()反序列化时先调用

0x01 Composer(php包管理工具)

Composer用autoloading技术还可以自动导入三方依赖库中的类(只需要在php文件开头加 require DIR.’/vendor/autoload.php;’)

0x02 序列化后数据含义

运行

<?php
class tom0li{
	var $test = 'abc';

}
$class1 = new tom0li;
$class1_ser = serialize($class1);
print_r($class1_ser);
file_put_contents('filename.txt', $class1_ser);
?>

serlialize序列化后数据

	O:6:"tom0li":1:{s:4:"test";s:3:"abc";}
	O:6: 这里O代表对象,(a则代表数组),6为对象长6字符,"tom0li"为对象名,1表示有一个值。
	{s:4:"test";s:3:"abc";} s表示字符串,4长度,"test"为值(i为int),($test="abc")

运行

<?php
class tom0li{
	private $test = 'abc';

}
$class1 = new tom0li;
$class1_ser = serialize($class1);
print_r($class1_ser);
file_put_contents('filename.txt', $class1_ser);
?>
	O:6:"tom0li":1:{s:12:"tom0litest";s:3:"abc";} 对象的私有成员具有加入成员名称的类名称;受保护的成员在成员名前面加上'* '。这些前缀值在任一侧都有空字节。 所以为s:12:"tom0litest"

0x03 常用magic函数

	__construct()实例化被调用
	__destruct()实例化对象完调用,
	__toString() echo一个对象被调用
	__wakeup()反序列化时先调用

0x04 SugarCRM v6.5.23 PHP反序列化对象

  1. 找反序列化的可控参数
  2. 找magic函数(__construct(),__destruct(),__wakeup())&上面的关键函数

‘service/core/REST/SugarRestSerialize.php’ 中的 ‘serve’ 函数

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));
        ...
    }
}

可控$data = !empty($_REQUEST[‘rest_data’]),from_html解码$data sugar_unserialize()

/**
 * Performs unserialization. Accepts all types except Objects
 *
 * @param string $value Serialized value of any type except Object
 * @return mixed False if Object, converted value for other cases
 */
function sugar_unserialize($value)
{
    preg_match('/[oc]:\d+:/i', $value, $matches);

    if (count($matches)) {
        return false;
    }

    return unserialize($value);
}

unserialize($value);然后找magic

public function __destruct()
{
    parent::__destruct();

    if ( $this-&gt;_cacheChanged )
        sugar_file_put_contents(sugar_cached($this-&gt;_cacheFileName), serialize($this-&gt;_localStore));
}

/**
* This is needed to prevent unserialize vulnerability
*/
public function __wakeup()
{
    // clean all properties
    foreach(get_object_vars($this) as $k =&gt; $v) {
        $this-&gt;$k = null;
    }
    throw new Exception("Not a serializable object");
}

sugar_file_put_contents

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']-&gt;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);
    }
}

file_put_contents写文件,把$data也就是$_this->_localStore传为数组,shell传为数组的值。 CVE-2016-7124 对象属性个数的值大于真实的属性个数时就会跳过wakeup 比如O:6:”tom0li”:1:{s:4:”test”;s:3:”abc”;}改为O:6:”tom0li”:2:{s:4:”test”;s:3:”abc”;} 跳过__wakeup防止清空

0x05 相同的方法或变量

POP chain利用的条件是找到的魔术方法不可以直接利用,但它有调用其它方法或者使用其它的变量时,可以在其它的类中寻找同名的方法或是变量,直到可以利用的点

<?php
class tom1 {
    var $test;
    function __construct() {
        $this->test = new one();
    }
    function __destruct() {
        $this->test->action();
    }
}
class one {
    function action() {
        echo "one";
    }
}
class two {
    var $test2;
    function action() {
        eval($this->test2);
    }
}

unserialize($_GET['admin']);

传入$test=two,从而调用two中的action(),payload如下

	O:4:"tom1":1:{s:4:"test";O:3:"two":1:{s:5:"test2";s:10:"phpinfo();";}}
0x06 参考

https://www.anquanke.com/post/id/86452 https://www.anquanke.com/post/id/84922

Written on March 8, 2018