做这题时遇见了新的函数和新的绕过,再次总结一下。
看一下题内代码
<?php
include 'utils.php';
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if ($guess === $secret) {
$message = 'Congratulations! The flag is: ' . $flag;
} else {
$message = 'Wrong. Try Again';
}
}
if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("hacker :)");
}
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
}
if (isset($_GET['show_source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}else{
show_source(__FILE__);
}
?>
题目代码不长,但就是让人很难受,出现几个让人摸不着头脑的新东西,为此看了师傅的文章慢慢理解了。
第一个新东西:$_SERVER['PHP_SELF']
它是读取当前脚本的文件名,通俗点就是读取文件夹里的一个文件。
例如url:www.baidu.com/aa/bb/index.php,它会读取/aa/bb/index.php,还比如www.baidu.com/aa/bb/index.php?id=1,它还是会读取/aa/bb/index.php。
本地测试一下:
会输出
第二个新东西:$_SERVER['REQUEST_URI']
这个通俗易懂,就是获取url的路径地址,继续测试一下
发现它会读取到我们传入的参数部分,简单来说,就是读取除域名外的所有路径地址,景观我们传入的参数名是否存在。
第三个新东西:basename函数
basename()返回路径的文件名部分。语法:basename(path,suffix)
path 必需,规定要检查的路径。 suffx 可选,规定文件扩展名,如果有这个文件名,将不会显示这个拓展名。
这个basename()函数则是读取url地址的最后一个文件,并输出。
分析题目
这些代码着实有些坑人了,刚开始做的时候总想在这里找到flag,但事实是这里的flag就是假的flag。好,看下面的代码。
一般情况下,flag就是在这个utils.php文件里,然而highlight_file可以将utils.php内的内容显示出来。然而我们需要绕过两个正则 。
看第一个正则,它会去匹配utils.php/(/可以是0次到无数次).
我们可以在utils.php后面添加不是/的任意字符,就可以绕过这个正则。接着我们需要绕过show_source,一般绕过姿势有show[source和show.source(记住即可)
最后我们要对show_source进行赋值,不能让他为空。
先看payload:
/index.php/utils.php/%88?show[source=1
%88为非ascll字符,为什么要用不可见字符?如果把%88换成a,$_SERVER['PHP_SELF']会读取到utils.php/a,basename函数就会只读取a并返回a,highlight_file就会显示a这个文件的源代码,这-明显是错误的。如果basename函数在读取到非ascll的字符时,就会停止读取路径了,就会返回utils.php,就可以达到我们想要的结果。
参考文章:https://www.cnblogs.com/yesec/p/15429527.html