知识点:

目录穿越_文件包含

static静态方法

参数传递引用

mb_strpos函数     mb_substr函数

正文:

页面有一张 滑稽 的表情包,查看一下页面源代码,发现提示

那就访问/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\" />";
    }  
?> 

可以看到有一个hint.php   访问一下

提示flag not here, and flag in ffffllllaaaagggg       得到了flag文件名

代码审计:

前面都是类中的代码,先看最后的代码


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

$_REQUEST 可以接收 GET POST COOKIE 传入的参数

需要存在file参数是字符串类型,并且经过emmm类中的checkFile方法返回true,才能执行include函数进行文件包含

这里没有创建emmm类的实例就可以引用其中的方法,是因为类中static表示是一个静态方法,可以通过类名直接调用,而不需要创建类的实例

目标明确之后开始看emmm类中的代码,类中也只有一个checkFile 方法,所以很简单,顺着往下看

给出了白名单,是source.php 和 hint.php   然后对参数page设置了条件

参数page就是传入的file数据,这里用了&$page,表示可以直接修改传入的变量,而不需要返回值来更新该变量

最终的目的是include $_REQUEST['file'] 包含其中有flag的文件,也就是ffffllllaaaagggg

目标就是让参数file也就是类中参数page包含ffffllllaaaagggg的同时满足checkFile方法返回true

首先page参数需要存在并且是字符串类型,然后if(in_array($page, $whitelist)) 这个判断是无法满足的,因为得有flag文件名,但是没影响,只要不返回false就行,接着往下看

$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
mb_strpos函数:  查找字符串在另一个字符串中首次出现的位置

mb_strpos ($haystack , $needle , $offset )
$haystack:被搜索的字符串
$needle:  要查找的字符串
$offset:  可选参数,指定从哪个字符开始搜索
//如果为正数,则从字符串的开头开始计算;如果是负数,则从字符串的末尾开始计算
//没有的话默认是0,即从开头开始搜索

mb_substr函数:  从一个字符串中提取子字符串

mb_substr ($str , $start , $length )
//substr() 函数只针对英文字符,而mb_substr()对于中文也适用
$str:    原始字符串
$start:  起始位置,如果为正数,则从字符串的开头开始计算;如果是负数,则从字符串的末尾开始计算
$length: 可选参数,表示要提取的子字符串的长度,如果没赋值,则提取从开始到字符串结束的所有字符

'.' 是 PHP 中的字符串连接运算符,它用于将两个字符串连接在一起,形成一个更长的字符串

在这里,它将 $page 变量的值和一个问号字符 '?' 连接在一起,形成一个新的字符串,在这个新的字符串中查找问号是否存在,那么很明显能找到

首先使用mb_strpos函数找到$page中第一个问号的位置,然后使用mb_substr函数将问号之前的部分赋值作为$_page进行处理
经过mb_strpos和mb_substr函数得到的$_page如果在白名单中,返回true

后面的代码对$page 进行url解密之后赋值给$_page,再次进行mb_substr函数得到新的$_page,再次判断是否在白名单中,不过如果传入的是正常的字符串,url解码之后还是本身,就没意义了
如果这一步进行完$page还不在白名单中,就会返回false
    
结合起来发现,只需要传入一个在白名单内的文件名(source.php或者hint.php)并在后面加上问号?

就可以保证在第二次if(in_array($_page, $whitelist))匹配查找的内容在白名单,返回true,退出checkfile方法,后面的urldecode代码都是用不到的
不在文件名后面加?问号的话代码自动加的?会添加在参数末尾,这样截取的内容就不满足白名单

关于include函数

这样的话,参数的格式就是source.php? + 文件名 

include()函数可以传入文件的绝对路径,也可以是相对路径

而参数是作为include()函数的参数执行文件包含的,绝对路径我们不知道,只能用相对路径

如果直接传入source.php?ffffllllaaaagggg,那么肯定会报错,因为没有这么一个文件名

实践出真知, 使用 include($_GET['file']); 这个简单的代码来简单说明一下

下图中的phpinfo.php是代码文件目录下面的一个php文件,abc是我随便输入的,没有这个目录,如果正常输入abc/phpinfo.php 是不行的,即使这个目录是存在的,也是会报错,因为格式不对

但是只要用../ 退回一级,就可以正常包含phpinfo.php

但是如果把abc 换成 abc? ,只要出现了? 那么就会报错

因为在windows文件名不能包含?

但是这里题目的环境是debian 不是windows系统  所以可以

那么这里搞清楚了,剩下的就是查找flag文件的具体路径了

从source.php?/ffffllllaaaagggg 开始,逐级用../进行目录穿越   经过四次目录穿越发现成功执行了命令,得到了flag

其实发现文件名也提示了我们要使用四层目录,文件名是4个f l a g


构造

http://node4.anna.nssctf.cn:28698/source.php?file=source.php?/../../../../ffffllllaaaagggg

即可得到flag



 

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部