[鹤城杯 2021]EasyP
[鹤城杯 2021]EasyP
题目来源:nssctf
题目类型:web
涉及考点:正则绕过
1. 还是先做代码审计
<?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[...]:是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等信息的数组。根据中括号内传入的参数不同,返回不同的信息,下面是题目涉及的两个参数:
'PHP_SELF':返回当前执行脚本的文件名。例如:在地址为
http://example.com/foo/bar.php
的脚本中使用 $_SERVER['PHP_SELF'] 将得到/foo/bar.php
'REQUEST_URI':取得当前URL的路径地址,感觉跟上面那个没啥区别
basename():返回路径中的文件名部分
接着我们看代码:
第一个if语句,当POST传入的参数$guest
等于$secret
时返回flag,但这里不知道$secret
是啥,先不管
第二个if语句,检查当前执行脚本的文件名,从后往前若找到utils.php
则过滤掉
模式分隔符后的"i"标记这是一个大小写不敏感的搜索
第三个if语句,检查当前URL的路径地址,若出现show_source
则过滤掉
第四个if语句,检查show_source
是否有定义
综上,我们先忽略POST传参,其次我们需要GET传入show_source
,使得路径包含我们需要查看的文件,利用文件包含highlight_file
使得页面回显php代码,即题目提示的utils.php
2. 构造payload
- 先明确我们需要构造的结构:
/utils.php/?show_source=1
这里show_source
随便定义即可
- 接着一个个过滤,先考虑第二个if语句,我们在
utils.php
后面加一个非ascii字符即可(因为是从后往前找,遇到非ascii字符就停了):
/utils.php/哈哈?show_source=1
- 再看第三个if语句,记住以下特性即可:
GET或POST方式传进去的变量名,会自动将
空格 + . [
转换为_
所以这里我们传入
show[source
先通过第三个if,在第四个if中GET传参的时候会转换回_
/utils.php/哈哈?show[source=1
- 第四个if就不用管了,定义了show_source即可
但是传入上述payload没回显,看其他师傅的wp说前面得加上index.php
,我也不知道为啥,总之最后payload如下:
/index.php/utils.php/哈哈?show[source=1
得到flag:
NSSCTF{0087c05c-80fd-47cb-b7c6-74c71fae9165}
第一个POST传参也确实是个坑吧,用来迷惑的
日期:2023.8.2
作者:y0Zero