2018-HCTF-Web-WarmUp

复现环境

https://buuoj.cn/challenges#[HCTF%202018]WarmUp

考察知识点

解题分析

访问题目是一个表情的图片,查看源码发现!--source.php-->,直接访问这个文件,可以看到题目源码。
分两部分来看,首先是checkFile函数

 <?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //设置白名单
            if (! isset($page) || !is_string($page)) { //$page值不为空且是字符串
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {   //判断$page是否在白名单里面
                return true;
            }

            $_page = mb_substr( // 用?来分割$page值
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page); //URL编码$page
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

我们来分析一下都有哪些检查:

  • 判断传入的参数不为空且为字符串
  • 判断是否在白名单里

mb_strpos — 查找字符串在另一个字符串中首次出现的位置
mb_substr — 获取部分字符串

  • 以问号分割再次判断引号前的部分是否在白名单

urldecode — 解码已编码的 URL 字符串

  • URL解码后再次判断引号前的部分是否在白名单
    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参数,传入checkfile进行过滤,如果通过过滤的话,就会通过文件包含显示文件内容。
接下来访问一下hint.php,看到提示flag not here, and flag in ffffllllaaaagggg
这时候基本可以确定要文件包含的是ffffllllaaaagggg,直接访问文件为404,说明flag文件不在同目录。
构造:
?file=source.php?/../ffffllllaaaagggg 绕过白名单检测可以到达第三个判断条件

_page = urldecode(page);此处是一个url解码,所以需要构造一个url编码的字符
?file=source.php%253f../ffffllllaaaagggg 此时就可以通过第四个判断条件
但还需要找到ffffllllaaaagggg文件的位置,通过../../../递归找到文件位置
?file=source.php%253f../../../../../ffffllllaaaagggg

至此成功获取到flag。

后来在网上发现不编码也可以解出来....应该是直接试出来的吧。
payload:
file=hint.php?../../../../../ffffllllaaaagggg或者 file=source.php?../../../../../ffffllllaaaagggg

推荐阅读更多精彩内容