web_warmup

0x01

进去以后一个笑脸,哈哈哈web_warmup_第1张图片
接下来我们查看源码
web_warmup_第2张图片
发现注释部分提示我们有个source.php,我们查看一下,结果如图
web_warmup_第3张图片
发现源代码


    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,我们看一下这个页面有什么东西没
web_warmup_第4张图片
页面显示如上图,提示我们flag不在这里,而是在这个ffffllllaaaagggg文件当中,结合源码大致内容,我们有了大致思路,就是文件包含执行代码,那接下来我们分析一下源码吧。

0x02源码分析

一、

 if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "
"
; }

那我们先看看它对传入的参数做了什么
1.判断变量file是否为空
2.判断变量file是否为字符串
3.调用定义的checkFile函数检查变量file
若上述条件都成功满足,那就include变量file,否则返回一个图片
所以接下来我们去看看他这个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;
            }

这里判断变量$page是否为空以及是否为字符串,很简单容易理解,不详细阐述,个别函数作用不知道的可以去学习一下php相关的函数

下一个走起

三、

if (in_array($page, $whitelist)) {
                return true;
            }

判断变量$whitelist中是否有 $page的值,这是in_array()函数的作用

语法

in_array(value,array,type)

参数

value 必需。规定要在数组搜索的值。

array 必需。规定要搜索的数组。

type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。
如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
如果没有在数组中找到参数,函数返回 false。
注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

四、

 $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );

这段代码有什么用,这段代码是截取变量$page首次出现?之前的值

五、

 if (in_array($_page, $whitelist)) {
                return true;
            }

判断变量$whitelist中是否存在变量 $_page的值

六、

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

这个跟上面那个作用和比较是一样的

0x03出招

既然我们对源码已经分析过了,知道源码对我们传入的参数都干了什么事情,我们要做的就是那些if语句返回true而不是false,那我们接下来就文件包含
payload:

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

这里解释一下,第一个问号是用来传参的,第二个问号是满足截取条件的,有人可能会有疑问,说,你这个源码分析有问题啊,源码中明明对_$page进行了url解码

$_page = urldecode($page);

你为什么不对第二个问号进行url编码呢?
那我来解释一下,其实这里编码不编码都不影响我们的结果,原因在于include

寻找包含文件的顺序先是在当前工作目录的相对的 include_path 下寻找,然后是当前运行脚本所在目录相对的 include_path 下寻找。例如 include_path 是 .,当前工作目录是 /www/,脚本中要 include 一个 include/a.php 并且在该文件中有一句 include “b.php”,则寻找 b.php 的顺序先是 /www/,然后是 /www/include/。如果文件名以 …/ 开始,则只在当前工作目录相对的 include_path 下寻找。

简而言之,如果include中出现了 …/…/…/…/…/…/那么就会忽略/前面的字符串直接进行查找,所以那个?编码不编码在这里不影响结果,只需要让它满足那个if检查语句就行了

当然,你进行编码也是没问题的,我们可以进行两次URL编码,将?变为%253f,然后上传,那么服务器在接受参数时会进行一次url解码,执行checkFile()函数时进行一次url解码,所以我们对?进行了2次URL编码。

执行结果:
web_warmup_第5张图片

0x04总结

本题主要考察的还是源码审计,主要是对php函数的作用和源码的理解,采取绕过姿势进行绕过或者满足判断条件,然后用到了一个include文件包含

你可能感兴趣的:(CTF—web)