• [HCTF 2018]WarmUp最详细解释


    查看源码找到提示

    访问source.php

    代码审计:

    1. class emmm
    2. {
    3. public static function checkFile(&$page)
    4. {
    5. $whitelist = ["source"=>"source.php","hint"=>"hint.php"];

    定义了一个名为emmm的类,在该类中有一个静态方法checkFile用于检查要包含的文件是否在白名单中,白名单是一个关联数组$whitelist,其中包含了允许包含的文件的键值对。在代码中,允许包含的文件有"source"=>"source.php"和"hint"=>"hint.php"。

    1. if (! isset($page) || !is_string($page)) {
    2. echo "you can't see it";
    3. return false;
    4. }

    checkFile方法首先检查传入的$page参数是否为字符串类型,如果不是或者未设置,将输出"you can't see it"并返回false。

    1. if (in_array($page, $whitelist)) {
    2. return true;
    3. }

    接下来,它检查传入的$page是否直接在白名单中存在,如果存在,返回true。

    1. $_page = mb_substr(
    2. $page,
    3. 0,
    4. mb_strpos($page . '?', '?')
    5. );

    然后它会对$page参数进行一系列处理:首先使用mb_strpos函数找到$page中第一个问号的位置,然后使用mb_substr函数将问号之前的部分作为$_page进行处理。

    注意:这个mb_strpos函数嵌套在了mb_substr函数中,准确说并不叫嵌套,而是将返回值作为了它的一个参数。

    说明:符号点 '.' 是 PHP 中的字符串连接运算符,它用于将两个字符串连接在一起,形成一个更长的字符串。在这里,它将 $page 变量的值和一个问号字符 '?' 连接在一起,形成一个新的字符串,在这个新的字符串中查找问号是否存在,那么很明显肯定能找到。

    也就是说 in_array() 函数的第三个参数length肯定为正数,又因为in_array() 函数的第二个参数start为0,因此会在字符串中的第一个字符处开始按照length长度进行截取,重新赋值给page。

    如果看到这里你没有明白,那么看完后面三个函数的详细介绍你就懂了

    下面是关于 substr()、strpos() 和in_array()函数的详细介绍和用法:

    (mb_strpos和strpos,substr和mb_substr在功能上几乎没什么区别)

    strpos(string,find,start)函数:

    返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。注意: 字符串位置是从 0 开始,不是从 1 开始。 

    参数描述
    string必需。规定被搜索的字符串。
    find

    必需。规定要查找的字符。

    start可选。规定开始搜索的位置。

    mb_substr(str,start,length,encoding) 函数:

    返回字符串的一部分,对于substr() 函数,它只针对英文字符, 而mb_substr()对于中文也适用。

    参数描述
    str必需。从该 string 中提取子字符串。
    start必需。规定在字符串的何处开始。
    • 正数 - 在字符串的指定位置开始
    • 负数 - 在从字符串结尾的指定位置开始
    • 0 - 在字符串中的第一个字符处开始
    length可选。规定要返回的字符串长度。默认是直到字符串的结尾。
    • 正数 - 从 start 参数所在的位置返回
    • 负数 - 从字符串末端返回
    encoding可选。字符编码。如果省略,则使用内部字符编码。

    in_array(search,array,type)函数:

    搜索数组中是否存在指定的值,找到值则返回 TRUE,否则返回 FALSE。

    参数描述
    search必需。规定要在数组搜索的值。
    array必需。规定要搜索的数组。
    type可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

    1. if (in_array($_page, $whitelist)) {
    2. return true;
    3. }

    之后再次检查传入的$page是否直接在白名单中存在

    1. $_page = urldecode($page);
    2. $_page = mb_substr(
    3. $_page,
    4. 0,
    5. mb_strpos($_page . '?', '?')
    6. );
    7. if (in_array($_page, $whitelist)) {
    8. return true;
    9. }

    将$_page进行URL解码,并重复之前的处理步骤,如果$_page在白名单中存在,返回true。

    如果上述条件都不满足,则输出"you can't see it"并返回false。

    1. if (! empty($_REQUEST['file'])
    2. && is_string($_REQUEST['file'])
    3. && emmm::checkFile($_REQUEST['file'])
    4. ) {
    5. include $_REQUEST['file'];
    6. exit;
    7. } else {
    8. echo "
      "
      ;
    9. }

    检查$_REQUEST['file']是否存在且为字符串类型,并调用emmm::checkFile方法进行检查。如果返回值为true,则通过include语句包含$_REQUEST['file']指定的文件并终止程序执行,否则输出一个图片标签。

    先尝试包含hint.php

    source.php?file=hint.php

    回显成功,flag在ffffllllaaaagggg

    注意:我们始终是在source.php页面下进行的传参操作,目的是利用include函数将flag文件包含出来,不要被这里的白名单搞混了。

    让我们来分析一下传入这个东西后,php代码是如何进行判断的:

    传入file=hint.php,首先检查'hint.php'是否是一个字符串,它是字符串,条件通过;

    检查'hint.php'是否在白名单中(白名单包括hint.php和source.php),在,继续执行后面的代码;

    对'hint.php'执行mb_substr函数,但是函数内一个参数是来自另一个函数mb_strpos的返回值,因此我们先看mb_strpos函数,使用.进行字符连接,即连接了一个问号字符 '?',得到hint.php?

    然后查找'?'在字符串'hint.php?'中第一次出现的位置,从0开始算,返回8,即length=8

    接下来我们执行mb_substr函数,即 mb_substr('hint.php',0,8)

    从字符串中的第一个字符处开始,返回8个字符,其实还是返回的hint.php;

    然后对返回的内容进行url解码,重复执行上面的检查和截取操作。

    我们只需要传入一个在白名单内的文件名(source.php或者hint.php),并添加上问号,这样可以保证每次找去用于检查的内容都在白名单,返回true。

    构造payload:

    source.php?file=hint.php?/../../../../ffffllllaaaagggg

    或者用 

    source.php?file=source.php?/../../../../ffffllllaaaagggg
    

    关于payload的解释:

    因为我们当前的source.php一般是在html目录下,往上是www,var,然后到根目录,flag一般就放在根目录下面,这里还有一个hint.php?/或者source.php?/,因此需要返回四层才能到根目录。

    拿到 flag{bc7e048e-19a6-4464-96b6-2d1569696875}

  • 相关阅读:
    Flink 窗口处理函数 WindowFunction
    Java程序设计复习提纲(上:入门语法)
    什么是API接口?API接口的类型,如何调用API接口?
    【附源码】计算机毕业设计JAVA成绩分析系统
    【算法题】136 137 只出现一次的数,及其变种
    面试官:你知道 Java 中的回调机制吗?
    MySQL高阶语句和视图
    第四章 决策树
    Stable Diffusion,Controlnet扩展
    【网络篇】如何在服务器之间建立互信
  • 原文地址:https://blog.csdn.net/Myon5/article/details/134286537