[ctf]HCTF 2018 warmup超详详详详解

打开以后发现是一个jpg图片,查看源代码

发现被注释掉的source.php

访问
在这里插入图片描述

发现了,因为high_file而被泄漏的源代码

发现除了source.php,还有hint.php

我们访问hint.php
[ctf]HCTF 2018 warmup超详详详详解_第1张图片

我们知道了flag在ffffllllaaaagggg中

接着我们来分析代码

 <?php  
    highlight_file(__FILE__);  
    class emmm  
    {    
        public static function checkFile(&$page)    
        {      
            $whitelist ["source"=>"source.php","hint"=>"hint.php"]; //白名单列表,可以查看source.php和hint.php            
            if (! isset($page) || !is_string($page)) {        
                 echo "you can't see it";        
                 return false;      
            }      //检验是否传入了page值
A           if (in_array($page, $whitelist)) {        
                   return true;      
            }      //检验page的值是否在白名单里
            $_page = mb_substr($page,0,mb_strpos($page . '?', '?'));  //$page . '?'将page的值后面补了一个问号,通过mb_strpos得到了page中到第一个问号前的长度,并通过mb_substr将此部分赋值给_page    
B           if (in_array($_page, $whitelist)) {        
                   return true;      
            }      //检验_page是否在白名单中
            $_page = urldecode($page);    //将_page解码  
            $_page = mb_substr($_page,0,mb_strpos($_page . '?','?')); //同上上步的操作     
C            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'])  ) { /*是否传入了file的值,file的值是否为字符串,将file的值放到emmm.checkFile中检验*/   
        include $_REQUEST['file'];    //如果成立,包含file
        exit;  
    } else {    
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";  
    } 
?> 

整体看过代码后,我们知道,如果有file值的传入,且file为字符串,而且通过了checkFile的验证,则将file文件包含。

那么我们的目的肯定是包含ffffllllaaaaggg

但发现,如果要通过checkfile的验证,叁个if return true的条件皆要使file或file的部分(因为有被截取的_page)为白名单中的source.php或hint.php。

在这里,我们就需要一个知识点

[ctf]HCTF 2018 warmup超详详详详解_第2张图片

(此图片来自https://www.likecs.com/show-355785.html)

即,当include后的文件找不到且有路径时,会沿此路径一直找,直到找到文件

我先给出payload(get方式),有四种:

一:?file=hint.php%3f/…/…/…/…/ffffllllaaaagggg

二:?file=hint.php%25%33%66/…/…/…/…/ffffllllaaaagggg(与这种相同的?file=hint.php%253f/…/…/…/…/ffffllllaaaagggg,只是在第二次url编码时,只将%编码了,实际上是一样的)

三:?file=source.php%3f/…/…/…/…/ffffllllaaaagggg

四:?file=source.php%25%33%66/…/…/…/…/ffffllllaaaagggg(第一种和第三种,第二种和第四种实质上是一样的)

如何理解呢

首先,url会自动解码一次

则到达checkfile处的:

一:file=hint.php?/…/…/…/…/ffffllllaaaagggg

二:?file=hint.php%3f/…/…/…/…/ffffllllaaaagggg

我们发现想要在第A个if处,就return ture 并且找到flag是不可能的

在第B个if处,经过前一步的mb_substr,_page变为 hint.php,所以return ture;

然后因为找不到,hint.php?,于是沿着路径四次返回上一层文件后访问ffffllllaaaaggg,找到了flag

这一层文件夹就是有source.php和hint.php的文件夹,所以第三,四种payload也能够访问flag

为什么我们会写出/…/…/…/…/ffffllllaaaagggg这个路径的,我承认我有赌的成分,但其实题目中的ffffllllaaaagggg给了提示,每个字母都四个

这时,我们就很容易理解为什么第三种payload也成立了,因为虽然在第B个if处,我们没能return ture,但是随后,又一次解码,得到file=hint.php?/…/…/…/…/ffffllllaaaagggg

$page . '?'后 page会连接一个问号变为hint.php?/…/…/…/…/ffffllllaaaagggg?

但是mb_strpos返回的是到第一个?的长度,即8

所以mb_substr截取的仍然是hint.php,于是return ture,后续就和上面的一样了

[ctf]HCTF 2018 warmup超详详详详解_第3张图片

[ctf]HCTF 2018 warmup超详详详详解_第4张图片

你可能感兴趣的:(php,web安全,安全)