HCTF2018-Warmup

0x01 代码审计

首先题目提示source.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. file参数为字符串。
  3. file参数经过checkFile函数检查后后返回True。

满足条件之后包含file参数所指定的文件。

0x02 in_array

首先我们看到checkFile函数声名了一个白名单,并且使用in_array函数,并且in_array函数第三个参数没有设定。首先想到的是in_array的弱类型转换。但看到后面还确实不是。
访问hint.php得到提示flag在ffffllllaaaagggg

0x03 “?”

  1. 先检查file参数是否在白名单中,如果存在则直接通过检验。

    if (in_array($page, $whitelist)) {
       return true;
     }
    
  2. 下面

    $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
    

    如果字符串不带?则直接返回原字符串。如果字符串带?,则返回?前的字符串。

  3. 继续对$_page进行检测。没啥说的。之后对$page进行url编码。再截取?前的字符串。

    $_page = urldecode($page);
    $_page = mb_substr(
        $_page,
        0,
        mb_strpos($_page . '?', '?')
    );
    
  4. 最后判断$_page是否在白名单中。

    $_page = urldecode($page);
    $_page = mb_substr(
        $_page,
        0,
        mb_strpos($_page . '?', '?')
    );
    
  5. 我们考虑绕过checkFile的限制才能包含我们想要的文件。代码先截取?前的字符串检测是否在白名单中。因此我们可以构造如下payload:

    ?file=hint.php?xxx
    
  6. 但如果我们这样构造在取?前字符的操作后后面我们想要包含的文件就被截断了。所以我们想到用url二次编码。这样在第一次服务器自动解码时paylaod长这样:

    ?file=hint.php%3fxxx
    

    之后的代码又进行一次urldecode,?后我们想包含的内容被截断,只剩下hint.php,符合要求,chechFile函数返回True.而此时$_REQUEST['file']值仍为hint.php%3fxxx,可实现目录穿越包含文件。
    payload:

    ?file=hint.php%253f/../../../../../fffflllaaaagggg
    

    最后一直在疑惑

    include hint.php%3f/../../../../../../ffffllllaaaagggg;
    

    是否能成功包含文件,在linux上试了一下,确实可以。

你可能感兴趣的:(ctf)