前言php
昨天在易霖博搞的網絡安全與執法競賽看到的一道web題,實際上就是用兩個原題湊起來的。。git
不事後面的一關沒見過這裏簡單記錄一下github
第一關web
打開是個登陸界面,和BJDCTF的簡單注入如出一轍,連密碼都同樣。。數組
第二關瀏覽器
登陸後獲得安全
即網絡
<?php ini_set('display_errors', 1); error_reporting(E_ALL); include 'flag.php'; //defines $flag class B { function __destruct() {//當一個對象銷燬時被調用或者腳本結束時調用 global $flag; echo $flag; } } if (isset($_POST['payload'])) { ob_start();//打開輸出緩衝區,全部的輸出信息不在直接發送到瀏覽器,而是保存在輸出緩衝區裏面,可選得回調函數用於處理輸出結果信息。 $a = unserialize($_POST['payload']); if ($a === False) { ob_end_clean();//清空(擦除)緩衝區並關閉輸出緩衝 } throw new Exception('Something tragic happened');//拋出一個錯誤 } ?>
仍是原題 Websec level 30app
payload:ide
a:2:{i:0;O:1:"B":0:{}i:0;i:1;}
詳細能夠參考:
[https://kangwoosun.github.io/webhacking/2020/03/28/Websec/]
[https://www.evonide.com/breaking-phps-garbage-collection-and-unserialize/#comments]
[https://www.evonide.com/fuzzing-unserialize/]
如下是我的的淺薄理解
若是傳入一個序列化的數組,而且這個數組中存在兩個或多個key相等的變量,那麼反序列化的時侯將刪除首先輸入的變量。所以,若是將類 B 對象做爲value冗餘,則將調用析構函數,而不會致使反序列化錯誤,即先解析 O:1:"B":0:{} 生成一個對象,而後在向後解析又遇到 i:0 因而將前一個 i:0 的值改成1,就至關於消滅了以前生成的對象因而觸發__destruct函數,以後也是冗餘的關係使得反序列化的結果返回的是 array(0=>1) ,不爲False,因而不會進入到ob_end_clean(),最後輸出flag
這題若是直接傳入
O:1:"B":0:{}
是不會輸出flag,由於雖然這樣反序列化獲得的a是一個對象不等於False,可是以後會經過throw new 拋出一個錯誤,它這裏的拋出錯誤就相似於下了一個斷點同樣,使得腳本程序的運行中止在了這裏,並無結束,因此反序列化後的B對象仍然存在,不會觸發__destruct