Buuctf-Web-[HCTF 2018]Warm Up 题解&代码审计

文章讲述了如何通过PHP代码审计,绕过网站的白名单限制,访问被注释或隐藏的文件,以找到flag的过程。关键步骤包括查看源代码,理解checkFile函数的工作机制,利用参数处理和目录遍历来构造payload.
摘要由CSDN通过智能技术生成

注:由于打开靶机的网址都会不一样,所以以下的url地址会不一样,但并不影响解题,可忽略。

做题过程

打开靶机
在这里插入图片描述
1、Ctrl+U查看源代码,发现有被注释掉的内容
在这里插入图片描述

我们访问一下这个被注释掉的文件,看看里面有什么
2、返回第一页的笑脸网页,在原来的url后面补充source.php

http://e79d31b6-19d7-40a3-a94a-4d8c8cf4a982.node4.buuoj.cn:81/source.php

这里如果我们在访问上一个源代码页面后再访问source.php后会出现下面这个界面
view-source:http://754e1f9d-22f3-4c64-8c4f-6d57f7655bfc.node5.buuoj.cn:81/source.php
[前面多了个view-source:(view-source:可查看当前页面源码)]
在这里插入图片描述
此时我们要查看一下这个页面内容,就把view-source:给删掉,然后就会出现下面这个页面。
我们进行代码审计
在这里插入图片描述

 <?php
    //显示当前文件的源代码
    highlight_file(__FILE__);
    //定义一个叫emmm的类
    class emmm
    {
    //定义函数checkFile,checkFile通过传入的参数来检测文件是否在白名单中
        public static function checkFile(&$page)  
        {
            //白名单列表,包含可访问的文件名和对应路径
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
     		//isset()判断变量$page是否已设置并且不为空
     		//is_string()检测变量是否是字符串,如果指定变量为字符串,则返回 TRUE,否则返回 FALSE
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }
             //in_array() 用于检查数组中是否包含指定的值
             //检测$page是否在白名单中
            if (in_array($page, $whitelist)) {
                return true;
            }
          
			//参数处理(解释在下面)
            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            //第二次检测$page是否匹配白名单列表$whitelist
            if (in_array($_page, $whitelist)) {
            //在白名单中,返回 true 表示可以访问文件
                return true;
            }
            //urldecode()解码URL字符串函数
            //对 $page 进行 URL 解码
            $_page = urldecode($page);
            //同上
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            //第三次检测$page是否在白名单中
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            //若无法访问文件则返回false
            return false;
        }
    }
      	 //1、empty()检查参数是否存在且非空
      	 //2、is_string()判断参数的值是否是一个字符串
      	 //3、emmm::checkFile()调用了emmm类的checkFile函数,检测参数是否在白名单中存在
    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\" />";
    }  
?> 

checkFile函数进行了三次白名单检查(只要有一次为true就行),两次参数处理。

参数处理部分的解释:

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

mb_substr()返回字符串的一部分
mb_substr( $str, $start, $length, $encoding )
$str,需要截断的字符串(必选)
$start,截断开始处,起始处为0(必选)
$length,要截取的字数(可选)
$encoding,网页编码,如utf-8,GB2312,GBK(可选)

这段代码的目的是从字符串 $_page 中提取出第一个问号 ? 之前的部分。

  1. $page 是一个包含某个 URL 中的参数部分的字符串。假设我们传入?file=source.php
  2. mb_strpos($page . '?', '?')
    • $page . '?' 会在 $page 字符串的末尾附加一个问号,得到一个新的字符串 source.php?。(为什么要加一个额外的问号呢?是为了确保即使在 $page 中没有问号时,也能找到一个位置返回。)
    • 然后,mb_strpos() 函数用于在这个新的字符串中查找第一个问号的位置。
  3. 找到了第一个问号在新字符串中的位置后,mb_substr() 函数就会从原始字符串 $page 中提取出从位置 0 到这个位置(不包括这个位置)的子字符串。
    • 这个子字符串就是原始字符串中第一个问号 之前的部分,也就是 $page 中的参数部分(不包括问号本身)。
      因此,$_page 变量将包含 $page 字符串中第一个问号之前的内容。
      $_page 的值将是 source.php

hint.php是白名单中的文件,我们也访问一下
在这里插入图片描述

我们整理一下已有线索:
(线索1):hint.php文件告诉我们flag在ffffllllaaaagggg中。我们猜测ffffllllaaaagggg是一个文件名,但是ffffllllaaaagggg并不在白名单中,所以我们要想办法绕过白名单访问到ffffllllaaaagggg。
上面的php代码告诉了我们:
(线索2):我们想要访问ffffllllaaaagggg,就必须让最后一段的if语句的三条检测都为true。
(线索3)checkFile函数会检查用户传入的参数($page)是否匹配白名单列表$whitelist。所以我们在构造这类查询语句时要包含白名单中的文件(source.php或hint.php)。并且checkFile函数是通过传入的参数 $page 来进行的文件检查,而不是直接从 URL 中获取参数。所以我们需要以参数形式传递文件名【?file=source.php】,将参数传给file,而不是直接访问文件路径【/source.php】。

  • 这里的参数名为什么是file?因为在最后的if语句中,if (! empty($_REQUEST[‘file’])…中的 ‘file’ 就是参数名。所以此处我们的参数名也只能是file。

(线索4):代码会截取第一个问号前的字符串并检查其是否在白名单中。
那我们让第一个问号?前的内容在白名单中,在问号?后面加上我们想访问的ffffllllaaaagggg。这样不就可以让ffffllllaaaagggg绕过白名单检测了嘛

我们在?file=source.php后加上?,然后加上ffffllllaaaagggg。即?file=source.php?ffffllllaaaagggg

根据已有线索,构造payload(下面source换成hint也行):

?file=source.php?ffffllllaaaagggg

没查到,可能文件不在当前目录中。
我们继续一层一层往上查,每次多添加一层../ 直到查到flag(../代表上一层目录)
(只写了后边部分)

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

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

  • 28
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值