[BUUCTF题解][HCTF 2018]WarmUp 1

打开页面未发现可用信息(除了一个特大的滑稽

 

 

查看源代码,发现一处提示,访问提示中的PHP文件

 

发现显示了源码,且其中提到了另外一个PHP文件hint.php(提示.php)

 

 暂且先访问hint.php文件,发现提示了flag所在位置

 

 返回source.php审查代码(从代码开始执行处

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\" />";
    }

 进行条件判断,条件为真时包含传入的参数file,那我们应该使条件为真来包含flag所在的PHP文件。而判断的条件为传入参数file不为空、传入参数为字符串、当传入参数file传入emmm类中checkFile函数时的返回值为真,这三个条件同时成立。前两个条件传入参数file时显然成立,则只需使第三个条件成立。

对emmm类的checkFile函数审查

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

第一处判断,参数page未被设置或不为字符串时条件为真,函数返回false,显然参数page不会使得该条件为真

第二处判断,参数page值存在于whilelist数组中时条件为真,函数返回true,但我们要包含的PHP文件并不在数组中

对参数page进行了处理(这里是引用传值,在函数外的参数file也会相应变化),涉及的函数如下

 

 

 

效果为将参数page进行截取,从参数page的值(字符串)开头截取第一次出现?的位置,如果参数page中不含?,就相当于没有进行处理 

第三处判断,参数page的值存在于whilelist数组中时条件为真,返回true。在这里可以构造一个payload,将存在于whilelist数组中的值和flag所在PHP文件用?拼接起来,运行到此处时即可让条件为真,返回true从而去执行关于包含部分的代码。

1号payload为:?file=source.php?./../../../../ffffllllaaaagggg

这里涉及到了另外两个知识,其中include()函数具有一个特点(虽然有这个特点,但博主本人在复现时使用了windows和linux系统均没有复现成功这个特点,迫不得已的不知所以的去用这个特点(可能单纯博主太菜了))。

 

所以在本题中include()函数包含文件时会按路径./../../../../ffffllllaaaagggg来寻找文件

另外关于路径,符号"."代表当前目录,“..”代表上一级的目录,"/"代表根目录,而./../../../../ffffllllaaaagggg则通过不断将路径跳转到上一个目录直到flag所在的PHP文件(该题中目标PHP文件恰好在根目录下,而根目录的上一层目录仍然是根目录,所以payload中../达到一定数目后即可)

因为存在第四处判断,所以还存在二号payload,这里接着代码看会看到第二次对参数page进行了处理,参数page先URL编码解码接着进行了与此前相同的截取处理。所以我们对?进行两次URL编码即可获得新的payload(编码两次是因为服务器会默认URL解码一次,只对?URL编码是因为include()包含的路径并没有第二次URL解码)

2号payload:?file=source.php%25%33%66./../../../../ffffllllaaaagggg

posted @ 2021-04-10 19:44  Article_kelp  阅读(258)  评论(0编辑  收藏  举报