攻防世界 WEB 高手進階區 HCTF 2018 warmup Writeup
攻防世界 WEB 高手進階區 HCTF 2018 warmup Writeup
題目介紹
題目來源: HCTF 2018
題目描述:warmup
題目考點
PHP程式碼審計
解題思路
-
常規操作 F12 看原始碼
-
url 輸入 http://220.249.52.134:37877/source.php 得到
<?php highlight_file(__FILE__); class emmm { public static function checkFile(&$page) { //白名單列表 $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //isset()判斷變數是否宣告is_string()判斷變數是否是字串 if (! isset($page) || !is_string($page)) { echo "you can't see it A"; return false; } //檢測傳進來的值是否匹配白名單列表$whitelist 如果有則執行真 if (in_array($page, $whitelist)) { return true; } //過濾問號的函式(如果$page的值有?則從?之前提取字串) $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?')//返回$page.?裡?號出現的第一個位置 ); //第二次檢測傳進來的值是否匹配白名單列表$whitelist 如果有則執行真 if (in_array($_page, $whitelist)) { return true; } //url對$page解碼 $_page = urldecode($page); //第二次過濾問號的函式(如果$page的值有?則從?之前提取字串) $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); //第三次檢測傳進來的值是否匹配白名單列表$whitelist 如果有則執行真 if (in_array($_page, $whitelist)) { return true; } echo "you can't see it"; return 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\" />"; } ?>
-
分析PHP原始碼看到
-
嘗試訪問 url http://220.249.52.134:37877/hint.php 得到flag提示 flag 在 ffffllllaaaagggg 中
-
回到之前的PHP原始碼,繼續分析
整體來看,這段PHP程式碼,是一個 emmm 類和一個 if else 分支,emmm類裡有一個 checkFile 函式
先看 下面的 if else
if (! empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file']) )
當前 請求的 file 非空 且 是字串 且 emmm::checkFile返回為真 時,條件成立
我們可以先直接留心最後的if/else邏輯,為了不看到最後那張無語的圖片,我們需要讓第一個if語句成立,並且最關鍵在第三個函式上。同時我們需要注意include檔案讀取函式是直接讀取file,從hint.php中我們知道flag在ffffllllaaaagggg中,所以這個字串要想辦法加入到 file 中進行讀取。
關鍵程式碼:$_page = mb_substr( $page, 0, mb_strpos($page . '?', '?')
函式簡介:
mb_strpos()
該函式有兩個引數,該函式的返回值是第二個引數在第一個引數中首次出現的位置(index)。
mb_substr() :函式返回字串的一部分
該函式有三個對應引數,第一個引數是操作字串,第二個引數是操作起始位置,第三個引數是操作字元長度。、
if (! empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file']) ) { include $_REQUEST['file']; //重要 exit;
那麼整體思路就是 滿足if 條件 繞過checkFile 函式, 最終要 通過 include 讀取 flag
嘗試構造解題 payload
http://220.249.52.134:30663/?file=hint.php?ffffllllaaaagggg 失敗,無回顯
我們其實已經可以從flag的檔名猜出一些真相了。我們需要將目錄回退四次,就像這美妙的名字一樣。
-
構造最終解題的 payload
http://220.249.52.134:30663/?file=hint.php?/../../../../ffffllllaaaagggg
總結
這道題用到的知識點有:
- 基礎php程式碼審計,考察三個函式: in_array、mb_substr、mbstrpos
- 考察include的一個小特性