BUUCTF 第一题截图思路
首先打开之后,一张笑脸,直接果断F12查看源码,发现注释代码 source.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" />"; } ?>
并且又发现了hint.php,我们打开一下,看到
告诉我们flag不在这里,并且告诉flag在ffffllllaaaagggg中,害,白高兴一场,不过我们继续往下学习
这是下面我们需要学习到的函数:
isset() : 判断变量是否被设置,如果变量值为null则返回false,反之返回true
is_string():用于检测变量是否为字符串,返回值也是布尔值
in_array(search,array,type):search和array是必需参数 ,search如果在array数组中,则返回true,如果type类型为true则search必须在数组中且给定的数据类型要和数组中的一致才返回true
mb_substr():字符串截取
mb_strsop():判断字符出现的位置
了解过这几个函数之后,我们就可以看看这个审计题,首先定义了个类 emmm
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语句
if (! empty($_REQUEST['file']) // file变量不能为空 && is_string($_REQUEST['file']) // file变量是否为字符串 && emmm::checkFile($_REQUEST['file']) // chechFile验证要通过 ) { include $_REQUEST['file']; //包含file变量中的文件 exit; } else { echo "<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" />"; }
然后我们回到checkFile函数
第一个if语句对$page变量进行检验,并且要求是字符串
第二个if语句看$page是否在$whitelist中
第三个if语句截取?前面的字符串,判断截取后的字符串是否存在于whitelist数组中,存在则返回true
第四个if语句判断截取后的字符串是否存在whitelist数组中。
如果四个语句都没有返回值,则返回false
第四个if语句中,先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,
checkFile函数中解码一次,仍会解码为'?',仍可通过第四个if语句校验。('?'两次编码值为'%253f'),
由于我们不知道ffffllllaaaagggg的位置,我们只能手动 ../ 慢慢试
最终得到了我们想要的flag:
flag{0fc800e1-cca4-41ac-9690-458cbb551c27}