[HCTF 2018]WarmUp 小白体验

Wubba lubba dub dub

buu上最简单的web题,攻防世界web进阶区也有。

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

本文记录本小白啃这道题的体验。是实况,做到哪写到哪。

进题,感觉小白在被鄙视:

image-20200311190737576

按F12开启控制台,看元素里有个注释写着source.php

直接访问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 和类外的if语句,类中的内容在那个if语句里被调用。

if语句做的事挺明白的,没学过php也能看懂,满足以下条件执行include:

  • file参数存在
  • file参数是string
  • file参数传如checkFile返回为true

前两个条件只要传了flie就能满足,看第三个条件在干什么:

checkFile($page):

$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
    echo "you can't see it";
    return false;
}

上来有个白名单,if语句表明,如果参数page是空的或者不是字符串,那就会返回false。

白名单里给了hint.php了,先访问下看看:

页面变化:

image-20200309213340530

大概意思是说flag在ffffllllaaaagggg这个文件里?结合刚开始看的那个if语句和白名单可以猜想如果能绕过checkFile里的白名单和if语句,那就能包含ffffllllaaaagggg这个文件拿到flag。

通读一下checkFile,这个函数里有4个if语句,在这四个if语句之间还有两次子串截取和一次urlDecode。捋了一下大概做这样的事:

  • 先确定参数存在并且是字符串
  • 检查参数是否在白名单
  • 如果不在白名单,对参数截取子串,截到 “?” 位置
  • 再次判断是否在白名单
  • 防止是url编码没转换,转码再截取 “?”
  • 最后一次判断白名单

如此我的目的就是,构造一个有ffffllllaaaagggg的字符串,并且在ffffllllaaaagggg之前有白名单里的内容和一个问号,比如:

hint.php?ffffllllaaaagggg

就用这个payload测试一下,结果:

image-20200311192049671

底部没有显示任何内容,没有在那几个if里输出 you cant see it也没在外层输出滑稽。所以这个checkFile绕过是可以的。但也没有输出什么跟ffffllllaaaagggg相关的东西,显然,路径是有问题的。而且ffffllllaaaagggg肯定跟当前页面不在一个目录里,不然就可以直接访问了。目测不能是扫描目录,应该就是向前找,也就是用../来向前找。

当前传入include的字符串是:”hint.php?ffffllllaaaagggg”

前面的hint.php和问号可以看做是一个目录,也就是在hint.php?后面加上一个”/“使其作为目录解析,然后用”./“来表示当前路径,再加上”../“向前访问。

最终在第四层输出了正确结果。

image-20200317154437750