攻防世界-Web-warmup

0x01

最开始映入眼帘的是一张图,查看网页源代码发现了提示:
在这里插入图片描述
进而访问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\" />";
    }  
?>

分析一下源码:

  • 后端读取从浏览器提交的file值
  • 判断file是否为空,判断file是否为字符串
  • 把file放到checkFile函数中去检查

若以上判断都满足就包含file文件。

接着我们来访问一下hint.php,这里面给出flag所在的文件是ffffllllaaaagggg。后面的目的就是构造一个payload使之能包含这个flag文件。

0x02

这里最关键的是绕过checkFile的检查,我们把这个函数划分为四个部分,分别为四个if语句判断。

  1. 该函数的参数必须为非空字符串
  2. 函数的参数应该是白名单里的其中一个元素,也就是source.php或者hint.php
  3. 如果以上两条不满足,对函数输入的字符串进行截取,截取从字符串开头到第一个?处,然后将截取下来的字符串与白名单比对
  4. 如果以上三条不满足,对刚刚截取下来的字符串进行一次URL解码,接着对解码后的结果再进行一次截取,并把截取的结果与白名单对比

一开始想着是要构造payload进行到最后一个if的判断,这样payload中就需要我们手动加入一个?字符来引导mb_substr函数来截取我们想要的字符串,那么payload的形式就必须如下:
file=source.php%253fxxxxxxxxxxxxxxxxx
构造%253f是因为:

  • 后端会自动对URL进行一次解码得到%3f(因为%的URL编码是%25),
  • 然后到第四个if的时侯会进行一次URL解码得到我们想要的?(因为?的URL编码是’%3f’)

这样虽然能够使checkFile()在接收非白名单输入时返回true,但是对于include函数我们的目的是要它包含ffffllllaaaagggg文件,所以需要配合include函数的特性来构造payload。

0x03

以下是从官方手册里找到的关于include的介绍:

The include statement includes and evaluates the specified file.
The documentation below also applies to require.
Files are included based on the file path given or, if none is given, the include_path specified. If the file isn’t found in the include_path, include will finally check in the calling script’s own directory and the current working directory before failing. The include construct will emit an E_WARNING if it cannot find a file; this is different behavior from require, which will emit an E_ERROR.
If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or …) — the include_path will be ignored altogether. For example, if a filename begins with …/, the parser will look in the parent directory to find the requested file.

概括一下就是:

  • 一般先从include_path里面找。
    通过phpinfo()可以看到自己的include_path设置
  • 第二从当前目录找
  • 刚刚是一般情况,特殊情况下,当指定的参数中包含路径,比如以\或者/或者.或者..开头,就会跳过include_path,到参数指定的路径去找

综上,构造如下payload就可以读取flag:
file=source.php%253f/../../../../ffffllllaaaagggg
注:…/的重复次数可以试出来,也可以根据flag文件的名字猜测
另外还可以在第三个if的时候就返回,这样就不要两次URL解码了:
file=source.php?/../../../../ffffllllaaaagggg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值