Nuaza的CTF解题记录---[HCTF 2018]WarmUp

[HCTF 2018]WarmUp

Keyword: Web PHP 白名单 字符串拼接 源码审计

解题思路:

进入靶场发现一张图片

image-20260908211633102

查看网页源代码发现注释,提示source.php

image-20260908211857424

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

分析代码得知,网站存在两个白名单界面source.php以及hint.php,只允许访问这两个页面。同时网页可以接受一个file参数,file参数会作为checkFile()函数的形参,在函数内部的实参为page

尝试访问hint.php,页面显示flag not here, and flag in ffffllllaaaagggg

尝试hint.php?file=ffffllllaaaagggg,页面无变化。

尝试source.php?file=ffffllllaaaagggg,页面回显you can't see it。回到代码分析,重点检查这部分字符串拼接代码:

$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );

mb_strpos(x, y)函数为查找字符串x中首次出现y字符的位置,具体到该函数则为查找 传入的page参数字符串接上一个单独的?字符这整个字符串中首次出现?的位置。

mb_substr(x, y, z)函数为截取字符串xy位置和z位置之间的字串。

源码中进行了两次以上操作,中间使用urldecode()函数以防止url加密形式的跳过。

举例说明这段代码的作用:

  • 若传入参数source.phpmb_strpos()函数中检查source.php?字符串中第一个?的位置,返回值为10。mb_substr()截取第0位至第10位的子串,结果为source.php
  • 若传入参数source.php?flagmb_strpos()函数中检查source.php?flag?字符串中第一个?的位置,返回值为10。mb_substr()截取第0位至第10位的子串,结果为source.php
  • 若传入参数?source.php?flagmb_strpos()函数中检查?source.php?flag?字符串中第一个?的位置,返回值为0。mb_substr()截取第0位至第10位的子串,结果为空值

因此,欲绕过该判断,仅需在输入的参数中人为添加两个?,让其返回空值。若两个?之间为任意字符串,则会因为不满足白名单而返回false,因此选择?file=source.php?/ffffllllaaaagggg?file=hint.php?/ffffllllaaaagggg作为payload输入。返回页面既没有报错也没有别的提示,仅为空页面,说明执行成功,不过当前目录没有该文件。

根据ffffllllaaaagggg的文件名推断其存在多层目录关系,因此尝试向前加入../遍历上层目录

最终的payload为/?file=source.php?../../../../../ffffllllaaaagggg

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

最终的flag为CTF2{4e0643af-4c7c-4c9a-b4e3-a36d3fdeeb12}

结束

posted @ 2026-09-08 22:14  Nuaza  阅读(4)  评论(0)    收藏  举报