知识储备
$_SERVER['PHP_SELF']函数是读取当前执行的php文件相对于根目录的位置。
例:http://1.14.71.254:28735/index.php/utils.php
读取的是/index.php/utils.php
$_SERVER["REQUEST_URI"]函数是读取得当前URI,也就是除域名外后面的完整的地址路径。
例:http://1.14.71.254:28735/index.php/utils.php
读取的是/index.php/utils.php
注:前面两者的区别是如果加了一个GET的传参的话,$_SERVER['PHP_SELF']的读取结果中不会出现传参内容而$_SERVER["REQUEST_URI"]的读取结果中会出现。
basename()函数是读取url地址的最后一个文件名(即最后一个 / 后的内容)。
例子:http://1.14.71.254:28735/index.php/utils.php
读取的是/util.php
注:basename()函数只能读取ASCII码,当读取到非ASCII码时会停止读取。
index.php 是php文件的入口文件当我们,使用index.php文件后我们才能加载出后面的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 :)");
}
这是一个正则匹配函数我们要绕过 utils.php/
其中斜杠可以零次或多次出现并且utils.php/匹配的位子是最后
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
这是一个正则匹配函数我们要绕过show_source
if (isset($_GET['show_source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
我们首先要GET到show_source的传参但是由于前面我们过滤了show_source所以我们要对其进行修改。我们可以将 _ 换成 [ 或 . 。(即用show[source或show.source)
highlight_file()函数可以帮我们读取文件内容。而代码段中只给我们了一个include 'utils.php';所以我们尝试读取utils.php中的内容
要basename()读取出utils.php 我们需要的代码形势是......./utils.php
或....../utils.php/非ASCII码形式
为了绕过utils.php出现在最后的正则我们舍弃第一种形式选择....../utils.php/非ASCII码形式
中文是非ASCII码我们可以用中文
于是payload可以写成 /index.php/utils.php/我是菜狗?show.source=1