[HCTF 2018]WarmUp 1

主页面是一个滑稽

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

通过源码得到hint.php,尝试包含改文件

得到flag在ffffllllaaaagggg
直接包含是失败的,所以这里需要分析源码。

分析file传参

追踪源码的接受参数file

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

判断是否通过$_REQUEST方法获取file传参,通过is_string函数判断必须是一个字符串,emmm:checkFile自定义函数判断file
所以这里继续追踪到checkFile()函数

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

定义了几种可以成功包含文件的条件

第一种可以绕过的条件

1.通过isset()判断,如果为空返回false,不为空返回true,这里取反,为空就是true,不为空就是false。还有is_string()判断,默认是字符串就为true,不为字符串就是false;这里也进行了取反,所以是字符串就是false,不为字符串就是true,所以这里字符串不能为空和不能不是字符串,否则会返回失败。
如果page在whitelist列表中,则会返回true。

所以如果绕过这里,file传入参数必须是source.php、hint.php,所以这里没有方法包含ffffllllaaaagggg

第二种可以绕过的条件

2.使用mb_substr()方法截取字符串,其中第二个值为截取的结束位置,mb_strpos()会获取第一个字符出现的位置;
所以这里就是通过mb_substr函数配合mb_strpos()获取第一个?出现的位置之前的内容

举例说明

?file=source.php  ->传入变为->  source.php?  ->通过mb_strpos()截取->  source.php

传入后默认会给我们的文件名加上一个?号,然后通过mb_strpos获取传入的文件名,最后判断文件名是否在whitelist列表中,如果存在则成功包含文件
这里可以进行绕过,payload如下

?file=source.php?./../../../../../ffffllllaaaagggg

得到flag
flag{adf218fe-948c-4a5d-8245-8bf91ff819d7}
payload分析,由于通过mb_strpos()函数获取?前面的内容判断是否存在列表,这里source.php、hint.php都可以为文件名,然后加入?后面提供传参,因为include()函数支持./、../这种相对路径,而且这关flag刚好在根目录下,所以可以得到flag。

第三绕过的方法

与第二种一样,不过对page多了一个urldecode()url解码的过程,这里可以使用二次编码绕过,将?编码两次进行绕过。
?的二次编码为%25%33%66
payload如下

?file=source.php%25%33%66./../../../../ffffllllaaaagggg

二次编码的原理是,中间件默认会进行一个url解码,然后传入PHP中又进行了一次解码,所以可以进行二次编码注入

posted @ 2022-09-05 09:57  Junglezt  阅读(111)  评论(0编辑  收藏  举报