NSS [鹤城杯 2021]EasyP
直接给了源码
<?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__);
}
?>
代码解析如下
1. `include 'utils.php';` 这行代码用于包含名为 "utils.php" 的外部文件。通过包含该文件,可以访问其中定义的变量和函数。
2. `if (isset($_POST['guess'])) { ... }` 这个条件判断语句检查是否存在名为 "guess" 的 POST 参数。它用于判断用户是否提交了一个名为 "guess" 的表单字段。
3. `$guess = (string) $_POST['guess'];` 这行代码将用户提交的 "guess" 表单字段的值转换为字符串,并将其赋值给变量 `$guess`。
4. `if ($guess === $secret) { ... } else { ... }` 这个条件判断语句用于比较用户提交的猜测值 `$guess` 是否与变量 `$secret` 的值相等。
- 如果两者相等,将会设置 `$message` 变量的值为 "Congratulations! The flag is: " 加上 `$flag` 的值,表示猜测正确。
- 如果两者不相等,将会设置 `$message` 变量的值为 "Wrong. Try Again",表示猜测错误。
5. `if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) { ... }` 这个条件判断语句用于检查请求的 PHP 文件名是否以 "utils.php" 结尾。如果是的话,会输出 "hacker :)" 并终止程序的执行,以防止直接访问该文件。
6. `if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){ ... }` 这个条件判断语句用于检查请求的 URL 是否包含 "show_source"。如果是的话,会输出 "hacker :)" 并终止程序的执行,以防止直接访问源代码。
7. `if (isset($_GET['show_source'])) { ... } else { ... }` 这个条件判断语句用于检查是否存在名为 "show_source" 的 GET 参数。如果存在,会使用 `highlight_file()` 函数显示show_source变量的源代码,并终止程序的执行。如果不存在,会使用 `show_source()` 函数显示当前 PHP 文件的源代码。
这段代码的作用是:根据用户提交的猜测值判断是否正确,并根据判断结果显示不同的消息。同时,对访问的文件和请求进行一些安全检查,以防止直接访问敏感文件或源代码。如果请求不符合预期的条件,会输出 "hacker :)" 并终止程序的执行。
这个题目出现了$_SERVER[‘PHP_SELF’]
这个是你调用的脚本的路径,意思就是读取文件夹下的一个文件
如果你访问的是
如下即为执行脚本的文件:
www.errorr0.com/errorr1/errorr2/ ------> /errorr1/errorr2/index.php
www.errorr0.com/errorr1/errorr2/index.php --------> /errorr1/errorr2/index.php
www.errorr0.com/errorr1/errorr2/flag.php ---------> /errorr1/errorr2/flag.php
www.errorr0.com/errorr1/errorr2/index.php?key=value --------> index.php
而$_SEVER[‘REQUEST_URL’]
它的值这个时候和$_SERVER[‘PHP_SELF’]的值是一样的。
区别在于,如果你用get传参的时候 S E V E R [ ′ R E Q U E S T U R L ′ ] 是会加上那个参数的,而 _SEVER['REQUEST_URL']是会加上那个参数的,而 SEVER[′REQUESTURL′]是会加上那个参数的,而 _SERVER[‘PHP_SELF’]不会。
www.errorr0.com/errorr1/errorr2/flag.php ---------> /errorr1/errorr2/flag.php
www.errorr0.com/errorr1/errorr2/index.php?key=value --------> index.php?key=value
basename函数返回路径中的文件名字。
如果你访问的是
http://1.14.71.254:28189/index.php/utils.php
那么它的值就会是utils.php
basename函数遇到非ascii字符时会将其舍弃
思路:
代码分析前四点都没有用,主要看这一段:
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__);
}
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
}
这个正则的绕过方法就是利用特性来绕过,可以用
[
(空格)
+
.
这些都可以被处理成_
if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("hacker :)");
}
这个正则是匹配末尾有没有/utils.php/+任意字符
绕过办法很简单
因为后面要调用basename,所以可以利用中文来绕过,中文不属于ascii编码中的。
payload:靶机网址+/index.php/utils.php/给我弗莱格?show.source=1
【可以放vps上试试】