[CTF/网络安全] 攻防世界 warmup 解题详析

[CTF/网络安全] 攻防世界 warmup 解题详析

在这里插入图片描述查看页面源代码,发现source.php

得到一串代码,进行代码审计:

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

这段 PHP 代码主要用于检测用户请求的文件是否在白名单之内,如果在则可以包含该文件并输出,否则直接输出一张图片。

下面对代码进行详细分析:

首先,在代码第3行定义了名为 emmm 的一个类,其中包含了静态函数 checkFile。该函数接受一个参数 $page,并对其进行三次预处理,分别进行 URL 解码、去掉查询字符串和转换成统一编码,然后依次与白名单中的文件名进行比较,如果匹配成功则返回 true;否则输出一条错误信息,并返回 false。

其次,在主程序中通过判断用户的请求参数 $_REQUEST[‘file’] 是否存在、是否是字符串类型,以及调用 emmm::checkFile 函数的返回结果来决定是否包含相应文件并输出。如果不符合条件,则直接输出一张图片。

hint.php中提示flag路径
在这里插入图片描述

姿势

要想包含特定的文件,则必须file参数存在参数为字符串类型调用 emmm::checkFile 函数的返回结果为true

代码细致审计

 $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
          


           if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }   //page参数存在且为字符串类型即可绕过该if





            if (in_array($page, $whitelist)) {
                return true;
            }  
//使用 PHP 中的 in_array 函数来判断 $page 是否在白名单 $whiteList 中。则参数在白名单中即可访问该文件

初步构造POC如下:

?file=source.php/ffffllllaaaagggg

接着审计该段代码:

         $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
           //使用 mb_strpos 函数查找 $page 中的问号位置,并截取从开头到该位置(不包括问号)的子字符串

假设传递的 $page 参数为:/path/to/file.php?id=qiu

使用 mb_strpos 函数查找 $page 中的问号位置:

$pos = mb_strpos($page . '?', '?'); 

返回的值为 17,表示第一个问号在字符串中的位置。
然后使用 mb_substr 函数截取从开头到该位置(不包括问号)的子字符串:

$_page = mb_substr($page, 0, $pos);

$_page 的值为 /path/to/file.php 即该段代码剔除了查询参数的文件路径。

再审计该代码:

          if (in_array($_page, $whitelist)) {
                return true;
            }
            //使用in_array 函数来判断 $page 是否在白名单 $whiteList 中。则参数在白名单中即可访问该文件






            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
           // 使用urldecode 函数对 $page 进行 URL 解码,然后再次使用 mb_strpos 和 mb_substr 函数重复上述操作





            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
       //使用in_array 函数来判断 $page 是否在白名单 $whiteList 中。则参数在白名单中即可访问该文件

由于PHP 在解析 include 或 require 语句时,会首先按照给定的路径进行搜索和加载。如果指定的路径是一个绝对路径或相对于当前脚本的路径,则直接按照该路径进行加载。

修改POC如下:(实现四次截断)

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

在这里插入图片描述


总结

该题考察代码审计。
我是秋说,我们下次见。

posted @ 2023-05-25 09:32  秋说  阅读(297)  评论(0编辑  收藏  举报  来源