1. 程式人生 > 其它 >攻防世界-web:warmup

攻防世界-web:warmup

題目描述

暫無

題目截圖

解題思路

訪問標題連結,發現圖片是個大大笑臉。直接看原始碼。

發現提示source.php,訪問source.php,得到php原始碼。

原始碼如下:

<?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_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 . '?', '?')
            );
            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\" />";
    }  
?>

分析原始碼:
1)接收一個請求引數file。
2)判斷請求引數是否為空,是否為字串,然後利用checkFile函式進行檢測。
3)檢測通過後,對file引數進行檔案包含。

該題主要是分析checkFile函式。經過分析checkFile函式,發現邏輯如下:
1)設定了一個白名單陣列,陣列內容為source.php,hint.php
2)判斷file引數值是否存在,是否為字串。否則返回false
3)判斷file引數值是否在白名單裡,如果在直接返回true
4)利用mb_substr、mb_strpos函式是對目標字串進行擷取操作,將擷取結果賦值給$_page引數。
5)判斷$_page引數是否在白名單裡。如果存在直接返回true,否則繼續執行。
6)對file引數進行url解碼賦值給$_page


7)利用mb_substr、mb_strpos函式是對$_page引數進行擷取操作,將擷取結果賦值給$_page引數。
8)判斷$_page引數是否在白名單裡。如果在就返回true,否則返回false。

基本過程就是上面所述,此題目標就是利用目錄穿越進行檔案包含,獲取flag。核心關鍵是構造的目錄穿越字串要能經過checkFile函式的檢測。
通過file引數賦值hint.php,可以知道flag在ffffllllaaaagggg檔案裡,所以只要能夠包含到此檔案即可獲取flag。

構造包含思路如下:
1)file=/ffffllllaaaagggg
2)file=../../../../ffffllllaaaagggg
但是以上兩個構造都無法通過checkFile函式檢測,直接會返回false。
我們再次分析checkFile函式流程,發現只要$_page

能夠匹配到白名單即可返回true。所以file引數經過字串擷取操作後,為source.php或hint.php即可。
我們發現checkFile函式裡進行了url解碼,我們知道瀏覽器到伺服器會進行一次url解碼,checkFile會再次進行一次url解碼,可以考慮二次url編碼。
我們還發現,字串擷取邏輯是在傳入的file引數字串後面拼接一個"?",然後去查詢"?"在file引數字串中第一次出現的位置,然後從0位置向"?"字元位置進行字串擷取。
例如:
file=hint.php?/../../../../123.php,則經過第一次擷取後的結果為hint.php,直接返回true。則會包含hint.php?/../../../../123.php,但是這個是無法構成目錄穿越的。
如果
file=hint.php%253f/../../../123.php,(其中%253f為"?"經過兩次url編碼的結果),則經過第一次擷取後返回結果為hint.php%3f/../../../123.php,不在白名單裡,則會進行url解碼後進行第二次擷取,url解碼結果為hint.php?/../../../123.php,對這個字串進行擷取後,擷取結果為hint.php,在白名單裡,返回true。則會包含hint.php%3f/../../../123.php,這個字串可以構成目錄穿越,伺服器會將hint.php%3f當作當前目錄下的一個資料夾。經過上級目錄穿越,最終將123.php進行包含。
所以最終payload為:
1)hint.php%253f/../../../../../ffffllllaaaagggg
2)source.php%253f/../../../../../ffffllllaaaagggg

得到flag

總結

1)理解目錄穿越原理
2)理解URL二次編碼後伺服器解析原理
3)能夠分析程式碼邏輯