拿到題,發現是一張圖,查看源代碼發現了被注釋掉的提示
<!-- source.php-->
step 1 在url傳參看看這個文件,發現了這道題的源碼
step 2 開始審計代碼,分析關鍵函數
-
//mb_strpos($haystack,$needle,$offset,$encoding):int|false 返回要查找的字符串在另一個字符串中首次出現的位置
-
$ haystack:要被檢查的字符串。
-
$ needle:要搜索的字符串。
-
$offset 可選:用于定義從何處開始搜索字符串,即搜索位置的偏移。如果沒有提供該參數,將會使用 0。負數的 offset 會從字符串尾部開始統計。
-
$encoding:可選。用于通過使用定義編碼mb_internal_encoding()。如果省略或是
null
,則使用內部字符編碼。
-
-
//mb_substr($str,$start,$length,$encoding) 中文截取函數:函數返回字符串的一部分。
-
$str:必需。從該 string 中提取子字符串。
-
$start:必需。規定在字符串的何處開始。
-
正數 - 在字符串的指定位置開始
-
負數 - 在從字符串結尾的指定位置開始
-
0 - 在字符串中的第一個字符處開始
-
-
$length:可選。規定要返回的字符串長度。默認是直到字符串的結尾。
-
$encoding:網頁編碼,如utf-8,GB2312,GBK
-
源碼中出現了:hint.php
step 3 url傳參查看hint.php,發現以下文字
flag not here, and flag in ffffllllaaaagggg
即獲得了flag文件名。
step 4 繼續分析代碼
<?phphighlight_file(__FILE__);
?class emmm//定義了一個名為emmm的類,在該類中有一個靜態方法checkFile用于檢查要包含的文件是否在白名單中,白名單是一個關聯數組$whitelist,其中包含了允許包含的文件的鍵值對。在代碼中,允許包含的文件有"source"=>"source.php"和"hint"=>"hint.php"。{public static function checkFile(&$page){$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//第①次檢查:checkFile方法檢查傳入的$page參數是否為字符串類型,如果不是或者未設置,將輸出"you can't see it"并返回false。if (! isset($page) || !is_string($page)) {echo "you can't see it";return false;}
?//第②次檢查:檢查傳入的$page是否直接在白名單中存在,如果存在,返回true。if (in_array($page, $whitelist)) {return true;}
?//對$page參數進行一系列處理:首先使用mb_strpos函數找到$page中第一個問號的位置,然后使用mb_substr函數將問號之前的部分作為$_page進行處理。$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));if (in_array($_page, $whitelist)) {return true;}
?$_page = urldecode($page);$_page = mb_substr($_page,0,mb_strpos($_page . '?', '?'));//第③次檢查:檢查傳入的$page是否直接在白名單中存在if (in_array($_page, $whitelist)) {return true;}echo "you can't see it";return false;}}
?
?//將$_page進行URL解碼,并重復之前的處理步驟,如果$_page在白名單中存在,返回true。如果上述條件都不滿足,則輸出"you can't see it"并返回false。if (! empty($_REQUEST['file'])&& is_string($_REQUEST['file'])&& emmm::checkFile($_REQUEST['file'])) {include $_REQUEST['file'];exit;} else {echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";} ?
?>
現在構造獲取flag的語句:hint.php?../../../../../ffffllllaaaagggg
傳入入checkFile函數要經歷:①白名單驗證 ②?過濾,過濾后就是hint.php ③白名單驗證,返回為真,則達成條件進行包含得到flag
注:include函數有這么一個神奇的功能:以字符‘/’分隔(而且不計個數),若是在前面的字符串所代表的文件無法被PHP找到,則PHP會自動包含‘/’后面的文件——注意是最后一個‘/’。
這里的ffffllllaaaagggg是在hint.php中發現的,顯然flag在這個文件里。其實文件名提示了我們要使用四層目錄。有四層目錄原理:source.php一般是在html目錄下,往上是www、var、根目錄,flag一般放在根目錄下,這里還有個hint.php?或者source.php?,因此需要返回四層才能到根目錄。
最終payload:
http://03b2cc85-7af4-439b-a06e-41da80ff6505.node3.buuoj.cn/index.php?file=hint.php?../../../../../ffffllllaaaagggg
注:若目標是根目錄,則可以多穿幾層,多穿無妨,少穿什么都沒有