Buuctf Web Warmup 菜鸟刷题之旅(代码审计)

<?php
highlight_file(__FILE__);//高亮
class emmm
{
    public static function checkFile(&$page)

    {
        //白名单列表
        $whitelist = ["source" => "source.php", "hint" => "hint.php"];
        //isset()判断变量是否声明is_string()判断变量是否是字符串 &&用了逻辑与两个值都为真才执行if里面的值
        if (!isset($page) || !is_string($page)) {//如果page非空或者page不是一个字符串
            echo "you can't see it A";
            return false;
        }
        //检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
        if (in_array($page, $whitelist)) {//判断page中是否存在白名单中的相关值
            return true;
        }
        echo '333:'.$page.'<br>';
        //过滤问号的函数(如果$page的值有?则从?之前提取字符串)
        $_page = mb_substr(//获取字符串的一部分
            $page,//检查的字段
            0,//开始位置
            mb_strpos($page . '?', '?')//返回字段长度//第一次出现的位置,返回$page.?里卖弄?号出现的第一个位置
        );

        //第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
        if (in_array($_page, $whitelist)) {
            echo 'h:'.$_page.'<br>';
            return true;
        }
        //url对$page解码
        $_page = urldecode($page);//解码url编码的page变量
        echo '1:'.$_page.'<br>';
        //第二次过滤问号的函数(如果$page的值有?则从?之前提取字符串)
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')//从?到?的长度
        );
        echo '2:'.$_page.'<br>';
        //第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
        if (in_array($_page, $whitelist)) {
            return true;//判断是否在白名单中
        }
        echo "you can't see it";
        return false;
    }
}
if(! empty($_REQUEST['file'])//$_REQUEST 数组 通过 GET、POST 和 COOKIE 输入机制提供给脚本的变量
    && is_string($_REQUEST['file'])//判断是否未字符串
    && emmm::checkFile($_REQUEST['file'])//将我们的的值传到emmm类里面的checkFile函数
) {
    include $_REQUEST['file'];
    exit;
} else {
    echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
//

最终绕过方式://file===source.php?/../../../../../../ffffllllaaaagggg

①告诉我们需要满足三个条件:

01.$file的值必须为非空;

02.$file是字符串;

03.$file传入checkFile()可以通过检验;

04.全部满足后,引用相应的文件

两个函数:

mb_strpos($string, $a):查找字符串a在字符串string中首次出现的位置,起始位置以0开始;

mb_substr($string, $start, $end):在字符串string中截取以start开始,以end结尾的子串;

01.白名单中有source.php和hint.php

02.$page的值必须为非空且是字符串

03.判断$page是否在白名单中

04.对page‘?′之前进行截取赋值给

_page,判断是否在白名单中

05.再对编码之后的$_page进行判断是否在白名单中

tips:include函数有这么一个神奇的功能:以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被PHP找到,则PHP会自动包含‘/’后面的文件——注意是最后一个‘/’。

这里的ffffllllaaaagggg是在hint.php中发现的,显然flag在这个文件里。其实文件名提示了我们要使用四层目录,这里比较坑。

(主要借鉴以下大佬博客:
https://www.cnblogs.com/zesiar0/p/12643084.html
https://blog.csdn.net/weixin_44866139/article/details/105455828
https://blog.csdn.net/qq_42967398/article/details/91127332

posted @ 2022-03-07 20:58  B1smarck  阅读(66)  评论(0编辑  收藏  举报