PHP反序列化漏洞

时间:2022-03-11 15:23:59
聊一聊PHP反序列化漏洞2016年11月4日反序列化漏洞在各种语言中都较为常见,下面就简单聊一聊PHP的反序列化漏洞(PHP对象注入)。第一次了解这个洞还是在某次ctf上,就简单记录下个人理解以及对CVE-2016-7124的简单分析。序列化与反序列化php允许保存一个对象方便以后重用,这个过程被称为序列化,序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。先看一眼具体什么样子name . '\'s phone is ' . $this->phone; }}$usr = new info();$usr->printdata();echo serialize($usr);?>此时输出church's phone is 111111O:4:"info":2:{s:4:"name";s:6:"church";s:5:"phone";s:6:"111111";}可以看到其中没有任何跟类有关的东西,只有其中的数据被数据化。O:4:"info":2:{s:4:"name";s:6:"church";s:5:"phone";s:6:"111111";}O:4:"info":2: 参数类型为对象(object),数组(array)为a。类名为info,有两个变量(参数s:4:"name";s:6:"church"; s:变量类型为字符串(数字为i),长度为4,名为name,值是长度为6的字符串churchs:5:"phone";s:6:"111111"; 长度为5的字符串phone,值是长度为6的字符串111111反序列化是将序列化后的字符串转换回一个数组对象。由于对象实例化和自动加载,反序列化可能会导致代码被加载并被执行。再看一下反序列化printdata();这时输出church's phone is 111111反序列化漏洞现在我们了解了序列化是如何工作的,那我们该如何利用它?因为反序列化对象的值是可控的,如果反序列化对象中存在魔术方法,而且魔术方法中的代码又能够被我们控制,漏洞就产生了,根据不同的代码可以导致各种攻击,如代码注入、SQL注入、目录遍历等等。影响:Joomla反序列化漏洞、SugarCRM v6.5.23 PHP对象注入漏洞、WordPress 3.6.1反序列化漏洞等。魔术方法php类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号”__“开头的,比如 __construct, __destruct, __toString, __sleep, __wakeup等。而这些函数在某些情况下是自动调用的,比如:__construct当一个对象创建时调用,相反__destruct当一个对象被销毁时调用__sleep方法在一个对象被序列化时调用,__wakeup方法在一个对象被反序列化时调用__toString当一个对象被当作一个字符串使用时调用name; } public function __construct() { echo '__construct'; } public function __destruct() { echo '__destruct'; } public function __toString() { return '__toString'; } public function __sleep() { echo '__sleep'; return array('name'); } public function __wakeup() { echo '__wakeup'; }}$usr = new info();$usr->printdata();echo $usr;$serialized = serialize($usr);echo $serialized;$unserialized = unserialize($serialized);$unserialized->printdata();?>这时会输出__constructchurch__toString__sleepO:4:"info":1:{s:4:"name";s:6:"church";}__wakeupchurch__destruct__destruct可以很清楚的看到这些魔术函数的自动调用,类似的魔术方法还有很多,这里不再一一列举。漏洞利用先看一个简单的demo:file)) { include($this->file); } } } $file = $_GET["file"]; if(isset($file)) { echo unserialize($file);}?>这个代码调用了Read类,并且有一个file值是我们可以控制的,所以构造类似这样的payload:test.php?file=O:4:"Read":1:{s:4:"file";s:11:"/etc/passwd";}这时仅需一个GET请求便能读取文件。CVE-2016-7124php前一段时间爆了一个漏洞(php bugs 72663 ),当反序列化一个对象时,假如属性发生了变化,就会导致__wakeup()中的return 0不会执行。简单来说就是当序列化字符串中表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup()方法。影响版本PHP5 < 5.6.25 、PHP7 < 7.0.10写了个简单的demo:正常情况下序列化后$serialized是这样的O:4:"info":1:{s:4:"name";s:6:"church";}执行之后,结果是这样的__wakeup__destruct可以看到__wakeup()方法被调用了。那把$serialized改成下面这个样子O:4:"info":2:{s:4:"name";s:6:"church";}再次执行之后,看结果__destruct由于表示对象属性个数的值大于真实的属性个数,很明显__wakeup()方法这次被跳过了。漏洞实例分析:SugarCRM v6.5.23 PHP反序列化对象注入漏洞分析