[HCTF 2018]WarmUp1

拿到题目后是一个滑稽的图像,通过开发者工具查看源码获得提示

[HCTF 2018]WarmUp1_第1张图片

访问指定页面后得到一串PHP代码,接下来尝试做代码审计

"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 "
"; } ?>

首先定义了一个名为emmm的类并包含了一个checkfile函数

首先看到的是一个$whitelist变量,翻译过来就是白名单,我们当前是source.php对应,还有hint.php,访问后获得提示

[HCTF 2018]WarmUp1_第2张图片
        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 是否已经被设置并且是一个字符串类型。如果 $page 没有被设置或者不是字符串类型,那么会输出 "you can't see it" 并且返回 false。

如果满足就执行下一个if,判断page变量是否在$whitelist中,是就返回ture

$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

mb_substr函数,就是从下标0开始截取$page字符串

mb_strpos函数做了一个查找,"."是连接符,"?"是查询字符串的开始符号。将变量值添加到查询字符串中。例如,如果page变量的值为"home",那么$page . '?'将生成字符串"home?"。将查找到的第一个?的下标作为mb_substr函数的参数

意思是如果变量中存在?,就将第一个?前的数据赋值给_page变量

然后检测_page变量是否在白名单中

mb_substr函数

mb_substr() 函数返回字符串的一部分,之前学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()

语法:
mb_substr ( $str ,$start [, $length = NULL [, $encoding = mb_encoding() ]] 参数:
$str:必需。从该 string 中提取子字符串。 $start:必需。规定在字符串的何处开始。
正数 - 在字符串的指定下标位置开始
负数 - 在从字符串结尾的指定位置开始

$length :可选。规定要返回的字符串长度。默认是直到字符串的结尾。
正数 - 从 start 参数所在的位置返回
负数 - 从字符串末端返回

$encoding:指定字符编码,可选
[HCTF 2018]WarmUp1_第3张图片

mb_strpos函数

语法:
mb_strpos ($str1 ,$str2 )
mb_strpos():返回str2在str1中首次出现的下标位置
参数:
$str1:要被检查的字符串。
$str2:要搜索的字符串。
[HCTF 2018]WarmUp1_第4张图片
            $_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;

接下来给_page变量重新赋值,使其等于URL解码之后的$page,并截取第一个问号(?)之前的部分。然后,它将截取后的结果与whitelist数组中的元素进行比较。如果截取后的结果在$whitelist数组中,则返回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 "
"; }

它首先判断用户请求中是否包含了名为"file"的参数,并且该参数的值是一个字符串,并调用一个emmm类中名为"checkFile"的方法来检查该字符串。如果这些条件都满足,则将该文件包含到当前的代码文件中,并退出程序。否则,将显示一张图片,并终止程序的执行。

构造payload

通过查看wp,都说文件位于网站根目录,所以首先我们应该初步构造payload,../的数量没有要求,够多就行(最多也就到根目录)

?file=source.php?/../../../../ffffllllaaaagggg

然后因为在chackfile函数中对字符串进行了编码,所以这里其实是经过了两次解码,第一次是发去服务器,服务器解析一次,第二次是urldecode。又因为检查的是?,所以只需要?需要逆推回两次

[HCTF 2018]WarmUp1_第5张图片

所以最终payload就是

?file=source.php%253F/../../../../ffffllllaaaagggg

你可能感兴趣的:(PHP,php)