攻防世界:WEB——warmup

题目:warmup,没有提示,点进去,一个表情包:

源代码里提示了一波,有个source.php的文件可以看

打开source.php,好家伙,代码审计

在这里插入图片描述

观察到有个hint.php的文件:打开它

在这里插入图片描述

并不是flag,但是提示我们flag在ffffllllaaaagggg里,看来要回到代码审计,仔细看代码了:

代码如下:

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

关键就是在于:include $_REQUEST['file'];这个代码,如何一步一步走到这里把我们构造的参数传递进去呢?

先看类之外的代码中的if条件:

 if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) 
  • 我们的file传参不能为空
  • 我们的传递的参数一定要是字符串
  • 我们一定要通过emmm类的checkFile的过滤,返回值一定要是true

再看checkFile这个拦路虎:

$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在$whitelist里面,即你只要传递的是source.php和hint.php,它就给你过,这就是为什么我们能打开那两个文件。
当然我们下次输入肯定是别的东西了:
再来看看下面

$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

mb_substr()的用法如下

mb_substr(
    string $str,
    int $start,
    int $length = NULL,
    string $encoding = mb_internal_encoding()
): string

mb_strpos -查找字符串中第一次出现字符串的位置
所以$_page是字符串$page中从头到第一个?的位置中间所有的字符串

接下来审计:

$_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;

把参数作为urldecode解析,然后后面就和上面一模一样:

也就是说来说去,它可以当做URL解析是吧
害,太简单了,我们在传统的URL后面加上我们的payload就好了。

http://111.200.241.244:59152/?file=source.php?/../../../../../../ffffllllaaaagggg

前面需要加上?file=进行传参,需要多试几次,这个目录比较难找

这个include下如果没找到一个文件,会告诉你它在哪个文件下:
详见:https://www.php.net/manual/zh/function.include.php

flag{25e7bce6005c4e0c983fb97297ac6e5a}

参考但不照搬:https://blog.csdn.net/qq_42016346/article/details/104199710

posted @ 2021-08-17 16:46  Zeker62  阅读(221)  评论(0编辑  收藏  举报