Web_XCTF/BUUCTF_WriteUp | warmup

发布时间 2023-12-07 11:22:29作者: Guanz

题目

分析

F12 查看源码,发现注释 <!--source.php-->,作为参数接入 url 提交,得到 php 代码:

稍做分析:

 <?php
    highlight_file(__FILE__);    // 对当前文件进行 PHP 语法高亮显示
    class emmm                   // 构造类emmm
    {
        public static function checkFile(&$page)  // 建立公有静态函数checkFile,参数引用变量page
        {
            // whitelist数组source的元素赋为字符串source.php,hint的元素赋为字符串hint.php
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];

            // 如果page变量未设置或page变量不是字符串
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";  // 输出you can't see it
                return false;             // 返回false
            }

            // 如果page变量的值在数组whitelist中
            if (in_array($page, $whitelist)) {
                return true;              // 返回true
            }

            // 将page字符串中第一个“?”前的子串赋给_page
            $_page = mb_substr(                                        
                $page,                       // 原字符串
                0,                           // 开始位置下标
                mb_strpos($page . '?', '?')  // 在page变量字符串后连接“?”,返回“?”在字符串page中第一次出现的位置,作为mb_substr函数的提取长度
            );

            // 如果_page变量的值在数组whitelist中
            if (in_array($_page, $whitelist)) {                        
                return true;               // 返回true
            }

            $_page = urldecode($page);     // 对page变量的值进行url解码赋给_page变量

            // 将_page字符串中第一个“?”前的子串赋给_page
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );

            // 如果_page变量的值在数组whitelist中
            if (in_array($_page, $whitelist)) {
                return true;               // 返回true
            }
            echo "you can't see it";  // 输出you can't see it
            return false;             // 返回false
        }
    }

    if (! empty($_REQUEST['file'])             // 如果以get或post请求得到file值
        && is_string($_REQUEST['file'])        // 且以get或post请求得到的file值是字符串
        && emmm::checkFile($_REQUEST['file'])  // 且向emmm类中的checkFile函数传递由get或post表单得到的file参数并返回true
    ) {
        include $_REQUEST['file'];  // 包含file的值
        exit;                       // 退出脚本
    } else {                                   // 否则
        // 输出滑稽图片
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?>


看到 include 函数,猜测是文件包含漏洞。包含条件是 file 值存在且为字符串,同时 file 值限定为以下四种可能:

  1. source.php
  2. xxx?source.php(xxx为任意长度不带 “?” 符号的字符串)
  3. hint.php
  4. xxx?hint.php(xxx为任意长度不带 “?” 符号的字符串)

这种情况或许可以通过对 “?” 符号后的字符串进行一些操作。


先看看 hint.php 文件:

ffffllllaaaagggg 可能是 flag 的文件名。


PHP 文档对 include 函数的文件查找路线解释为:“被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 include 最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则 include 结构会发出一条 E_WARNING”


根据 file 的要求和 flag 文件名构造 url,在第五级父目录找到 flag:

payload:?file=source.php?../../../../../ffffllllaaaagggg,其中 source.php 仅用于通过函数 checkFile 的过滤,更换为 hint.php 同样可通过。

Flag

XCTF:flag{25e7bce6005c4e0c983fb97297ac6e5a}
BUUCTF:flag{427773f9-b1a6-49b1-8402-97ad11968d2d}

参考

PHP 代码审计-CTF Wiki
PHP 教程-菜鸟教程
php class类的用法详细总结-左正-博客园
PHP之static静态变量详解-心雨星空-博客园
PHP中private、public、protected的区别详解-周伯通之草堂-博客园
php中引用符号(&)的使用详细介绍-梦入烟城-CSDN
mb_strpos (Encoding)-PHP 中文开发手册-开发者手册-腾讯云开发者社区
php 中 \$_GET、\$_POST 和 $_REQUEST 的区别?
PHP 类与对象 —— 范围解析操作符(::)-终毅衝-CSDN
PHP_ include-Manual
Linux基础命令之cd返回上级目录/返回根目录/进目录/返回上一次目录/返回指定目录-Soinice-CSDN