1. 项目概述这到底是个什么问题先把这个话题说透。命令执行漏洞又称RCERemote Code Execution在渗透测试和漏洞挖掘里一直是高危级别的存在。攻击者一旦拿到命令执行点基本上等同于拿下了服务器的半条命。但现实情况是拿到命令执行点只是开始目标系统里的过滤规则、安全设备、WAFWeb应用防火墙并不会让你舒服地执行命令。而通配符绕过正是绕开过滤限制的经典手法之一尤其当过滤机制只做了简单的字符串匹配阻挡了“空格”“管道符”“分号”等常见分隔字符却没有对通配符做严格限制的时候整个防线实际上已经出现了裂缝。简单来说这个项目的本质就是探讨如何利用系统通配符的展开机制在过滤规则只检查关键字而不检查特殊符号的场景下完成命令拼接与执行。很多人第一次听说会觉得“就这”但真正在实战中踩过坑的都知道通配符绕过看起来简单真正落地的时候坑很多比如通配符匹配不到文件、参数位置不对、命令长度受限等等。这篇文章会从原理、实操、绕过思路到对应防御手段把这条线完整讲清楚。适合谁看如果你是安全研发、WAF规则运维、渗透测试初学者或者在做代码审计时遇到过命令拼接类漏洞但不知道怎么系统化绕过与防御这篇文章会帮你把思路理清楚。我不讲空话直接上干货。2. 通配符绕过的核心原理拆解2.1 通配符的本质是Shell的“展开”机制要理解通配符绕过先得理解一个事实通配符不是命令本身的功能而是Shell在解析命令时做的事。以Linux系统为例Bash在收到一条命令后会先对命令字符串进行词法分析把其中有特殊含义的字符比如*、?、[、{进行路径展开。展开的意思是Shell会把*.txt这个模式去匹配当前目录下的文件名如果匹配到a.txt b.txt它就会把*.txt这个字符串替换成a.txt b.txt再执行。这个机制和过滤有什么关系关系大了。很多WAF和代码层过滤规则检查的是开发者能“猜到的”危险字符和危险命令。比如过滤/bin/sh、过滤cat、过滤flag、过滤空格。但过滤脚本很难对所有通配符组合做穷举因为通配符展开之后进入了命令参数或者命令本身的位置最终被执行的会是展开后的字符串而不是你传进去的那一串原始内容。这个时间差就是绕过空间。举一个最朴素的例子。过滤规则拦截了cat字符串你直接提交cat /etc/passwd会被拦。但如果你构造c\at /etc/passwd、/bin/c?t /etc/passwd或者用ca[t] /etc/passwd就可能绕过去因为正则规则匹配的是cat而Shell展开后正好是cat。2.2 为什么空格是绕过的重灾区深入一点说命令执行漏洞里最头疼的往往不是命令关键字而是空格。空格在很多过滤场景下是第一个被处理的符号。为什么因为绝大多数命令拼接格式都非常依赖空格比如cat /etc/passwd中间的空格就是天然分隔符。过滤规则往往简单粗暴不允许出现空格出现就直接拦截。这里就要用到通配符的另一种特性了。Bash在路径展开之外还有一些特殊的变量展开机制。比如${IFS}这个变量在Bash里默认是空格、Tab、换行的一组字符。你在命令中写${IFS}Shell在展开变量的时候会把它替换成空格字符。所以cat${IFS}/etc/passwd在命令执行时等价于cat /etc/passwd但如果过滤规则只匹配空格和%20那么你提交cat${IFS}/etc/passwd过滤规则如果没处理${和}这类字符直接就被放行了。2.3 通配符的几种典型形式通配符在绕过场景里远比很多人想象中丰富。列一下常见的几种*星号匹配任意长度的任意字符包括空字符串。常用于模糊匹配文件名但也经常被用来代替命令名或参数的一部分。?问号匹配恰好一个任意字符。比如c?t能匹配cat、cbt、cct只要中间恰好是一个字符。[...]字符集匹配匹配括号内任意一个字符。比如ca[t]就是cat[c-f]at可以匹配cat、dat、eat、fat。[!...]或[^...]反向字符集匹配不在括号内的任意一个字符。{...}花括号展开它比路径展开更早发生用于生成多个字符串。比如{cat,echo} /etc/passwdShell会把它展开成两条命令依次执行。实际在绕过中前三种用得最多但花括号展开往往能带来惊喜因为它的行为和路径展开略微不同很多过滤规则完全没考虑这一层。2.4 命令名的通配符替代理解了展开机制很自然的思路就是不仅可以对参数做通配符处理命令本身也能用通配符代替。假设目标系统里存在/bin/cat而你提交的原始参数被过滤规则检查时“cat”这个子串被拦截。此时如果构造/bin/c?t /etc/passwdWAF的规则可能只检测命令首段是否匹配已知黑名单命令/bin/c?t不在黑名单里于是放行。等到Shell真正执行时路径展开把/bin/c?t匹配成/bin/cat命令照常执行。这里有一个前提条件就是目标目录下不能有多个能匹配上这个模式的文件。比如你写/bin/c?t如果恰好/bin下有一个cat但也有一个cut那么?展开会同时匹配到/bin/cat和/bin/cutShell会尝试把/bin/cat /bin/cut一起执行这往往会导致命令报错或者产生不可预期的结果。所以实际利用中通常需要先了解目标环境的结构越了解构造的通配符越精确成功率越高。3. 绕过场景建模与前置条件分析3.1 典型的过滤规则模型在深入学习具体绕过方式前先建立一个概念框架。实际项目中遇到的过滤规则基本上可以归为三类这三类的绕法思路完全不同。第一类是黑名单过滤。维护一个危险命令和危险字符的列表只要输入串匹配到黑名单就拦截。这类过滤最脆弱因为它只认识它认识的东西你稍微变换一下写法它就不认识了。经典的绕过方式有字符串拼接、编码绕过、大小写混合、通配符插入等。第二类是白名单过滤。只允许特定字符集和特定格式的输入其余全部拒绝。这类过滤相较而言更安全但也不是铜墙铁壁问题往往出在白名单本身设计不合理比如允许了${}却不知道它会被展开允许了*却不知道它会被路径展开。第三类是语义分析过滤。这类已经接近WAF的更高阶形态了它会尝试还原你输入的最终意图甚至模拟Shell的展开结果来判断是不是恶意命令。但即便这样绕过仍然可能因为通配符展开依赖目标服务器的文件系统状态你无法在WAF层完全预测Shell在所有场景下的展开结果。在真实业务中绝大多数情况是三类混用但底层大多还是黑名单思路。这也就解释了为什么通配符绕过在今天依然有效黑名单再长也长不过Shell的展开机制。3.2 绕过的前置条件清单通配符绕过不是万能的它对运行环境有比较明确的要求。我在实际测试里总结了一份前置条件清单供你对照判断目标系统是类Unix环境Linux、Unix、macOSWindows的cmd和PowerShell对通配符的处理机制不同绕法也完全不同。命令执行漏洞点支持传入多字符参数而不是只能传单个数字或固定字符串。过滤规则关注的是命令和参数的“关键字”而不是限制参数长度和特殊字符种类。目标环境中有可以被通配符匹配到的文件或目录满足路径展开的条件。执行的Shell具备正常的展开功能Bash、Dash、Sh均可C Shell部分行为不同。如果你判断当前漏洞点不满足以上条件那通配符绕过大概率行不通需要考虑别的路子比如换行符分隔、十六进制编码、环境变量拼接等但那些不在本文重点范围内。3.3 为什么说“简洁版”不等于“简单版”标题里写着“简洁版”但实际处理过类似问题的同行都清楚越是基础的手法越要精细控制。很多新手一上来就写cat /etc/passwd被拦了就换个cat${IFS}/etc/passwd还是被拦就不知道下一步怎么走了。原因在于他缺少一个系统的测试思路没有先探测过滤规则、没有构造分步测试的Payload、没有观察哪些字符能过哪些不能过、没有根据报错信息反推过滤规则的匹配逻辑。我习惯的做法是把一次绕过拆成四个阶段来推进第一阶段探测过滤边界第二阶段构造基础Payload第三阶段在基础Payload上叠加变形第四阶段在目标环境实测并调整。每个阶段都有对应的测试方法和判断标准而不是盲目堆Payload。下面的实操部分就按照这个思路来展开。4. 实操全记录从探测到完整绕过4.1 第一阶段探测过滤规则的边界拿到一个漏洞点之后我第一个动作永远不是急着打Payload而是先搞清楚对面的过滤器到底拦了什么、放行了什么。这一步看起来简单其实非常考验细节。构造一组探测请求本质上是在测试字符能否通过。比如给每个可能用到的重要符号或命令字母单独发送一次观察响应码和回显差异。我常用的探测字符大致包括空格、制表符、$、(、)、、|、;、、、、、*、?、[、]、{、}、${IFS}、%0a等。对于每一种字符分别构造请求观察是否被拦截拦截通常会表现为400/403/406或返回统一错误页以及不被拦截时命令执行的结果是否出现差异。这里举一个实际探测的案例。假设目标存在一个Ping功能的参数系统拼接命令为ping -c 4 你的输入过滤规则未知。我先提交一个正常的IP127.0.0.1确保命令能执行。然后依次提交127.0.0.1;id、127.0.0.1|id、127.0.0.1id、127.0.0.1$(id)、以及带空格的127.0.0.1 id。观察哪一类请求被拦截。接着在确认;被拦截后再提交127.0.0.1%3bidURL编码后的分号看URL解码是否发生在过滤检查之前。这个探测信息量很大。它能直接告诉你过滤的位置是在应用层做了正则匹配还是WAF在HTTP层拦截还是系统层做命令黑名单检测。不同层级的过滤对应的绕过策略根本不一样。4.2 第二阶段构造基础Payload的五种经典姿势在完成了边界探测后就可以开始构造第一个能跑通的绕过Payload了。这里我按实战经验给你列五种最常用的姿势每种都附带一个最简示例和适用场景。姿势一利用?代替单字符适用场景命令关键字被拦截但通配符没有被处理。提交127.0.0.1; /bin/c?t /etc/passwd目标过滤规则如果匹配的是cat那么/bin/c?t就不中招。注意这里的命令名因为路径展开变成了/bin/cat。姿势二利用*模糊化命令路径适用场景命令执行环境相对简单比如/usr/bin下文件较少或者你能确定目标系统版本对应的命令路径。可以构造/usr/bin/c* /etc/passwd只要当前环境里匹配到的文件只有cat就能顺利执行。如果匹配到多个文件命令会报错但报错信息里往往会把匹配到的文件名带出来恰好可以当目录列举用。姿势三利用[...]精确匹配单字符适用场景需要避免多文件匹配的副作用而?太宽泛的时候用字符集能把匹配范围收紧到“必然命中目标文件”。比如cat可以写成ca[t]ls可以写成l[s]。这个技巧的隐蔽性比?和*更强因为正则引擎匹配“cat”字符串时ca[t]是匹配不上的。姿势四利用${IFS}替代空格适用场景一切因为空格被拦而无法拼接命令的情况。注意${IFS}和$IFS不一样$IFS在某些场景下替换的字符串末尾会带上空字符需要留意。实测最稳定的写法是${IFS}完整带花括号。另外$IFS$1也是一种变体$1是Shell位置参数默认状态下为空利用它可以起到分隔变量的作用。姿势五利用花括号展开{cmd,arg}适用场景过滤规则对逗号和花括号没有做限制时可以用花括号展开来绕过空格过滤。例如{cat,/etc/passwd}。Shell会把他展开成cat /etc/passwd而且整个展开发生在命令解析阶段WAF看到的只是{cat,/etc/passwd}一串很难直观判断其危险性。4.3 第三阶段基础Payload的叠加变形与混合利用真实场景里单一姿势往往不够用。过滤规则常常同时拦截命令关键字和空格甚至有更变态的会拦截“路径分割符号/”。下面讲几个常用的叠加技巧。第一个叠加思路是反斜杠绕过。很多过滤规则对反斜杠没有处理能力因为单个\在部分语言里不是正则的活跃字符。此时构造c\at /etc/passwdShell中反斜杠会转义后面一个字符最终执行时仍然是cat。把它和${IFS}叠加就能同时绕开命令关键字和空格的检测c\at${IFS}/etc/passwd。第二个叠加思路是利用环境变量拼接。比如你写${PATH:0:1}替换出来的结果是/因为PATH环境变量的第一个字符通常是/。如果你同时写了${PATH:0:1}etc${PATH:0:1}passwd展开后就是/etc/passwd。这种用法适合系统拦截了/字符的场景。但注意这个技巧对服务器环境较敏感如果PATH被改过就用不了需要先验证。第三个叠加思路是变量拼接命令名。假设ls被拦截但l和s单独不拦截可以用ls或l$s来绕过。$在Bash中展开为空或一系列参数配合字符串拼接效果显著。这种技巧适合过滤规则简单粗暴匹配单个命令字符串的情况叠加通配符也能用/bin/l$s或者l$s${IFS}/etc。第四个思路是换行符与注释符号的组合。有的过滤是按行检测的也就是只检测第一行内容此时可以用%0a换行绕过。例如原命令是ping -c 4 127.0.0.1你提交127.0.0.1%0acat /etc/passwd#换行后新命令cat /etc/passwd在下一行执行#注释掉系统本来要拼接的尾部。这种方式和通配符无关但经常和通配符叠加使用形成双保险。4.4 第四阶段实战案例完整拆解上面讲了一堆原理和姿势现在用一个虚构但完全符合真实场景的案例走一遍完整流程。场景描述某公司有一个内部测试系统提供了一个通过Web页面执行系统命令的功能模块用于管理员查看服务器磁盘信息。Web后端逻辑大致是接收参数disk在Shell中执行df -h 你的输入然后返回输出结果。我只知道这个系统的过滤规则会对常见命令和符号做拦截但具体规则未知。第一步先用普通参数/?disk/tmp测试命令正常执行返回了df输出确认命令执行点存在。第二步做边界探测提交/?disk/tmp;id返回403拦截页。再提交/?disk/tmp|id同样403。再试/?disk/tmp$(id)有意思的是这个请求通过了返回结果里没有id的输出。这说明两条线索命令分隔符;、|被拦截$()没有完全被拦截但可能嵌套深度不够导致命令没执行或者被其他方式解析掉了。第三步验证通配符是否可用。提交/?disk/tmp*返回结果正常*符号没有被过滤。这是一个关键信息意味着路径展开机制可能可以利用。第四步构造通配符绕过Payload。既然;被拦截但可以通过换行符%0a来分隔命令。构造/?disk/tmp%0a/bin/c?t${IFS}/etc/passwd。这里同时用到了三个技巧换行符做命令分隔、?代替at中的a、${IFS}代替空格。实际执行结果成功返回了/etc/passwd的内容。第五步优化Payload减少噪音。上面的Payload已经成功但里面带了明显的passwd字样如果目标有第二层过滤会很难堪。继续优化为/?disk/tmp%0a/bin/c?t${IFS}/etc/p*sswd这样过滤规则连passwd都匹配不到了但通配符展开后仍然是/etc/passwd。同样如果系统还拦截了bin、etc可以继续用/?通配符替换/b?n/c?t${IFS}/etc/p*sswd。这个案例里最关键的一步是什么是对*符号未被过滤的确认。没有这一步后面所有操作都是盲猜。很多新手上来直接堆Payload往往就是因为跳过了探测环节导致连自己失败的原因在哪里都说不清楚。5. 难点突破当通配符也失效时的备用方案5.1 通配符失效的四种典型原因实践中总会遇到通配符绕不过去的情况。总结下来最常见的原因有下面几种必须逐一排查。第一种情况目标环境不是Bash系。部分特殊环境使用sh的POSIX模式时通配符行为基本一致但某些嵌入式设备或精简系统使用的Shell对花括号展开支持不全。这种时候就要优先用?和*避免花括号方案。第二种情况匹配到了多个文件导致命令执行失败。比如/usr/bin/c*在目标系统上同时命中了cat、cut、curl等多个文件Shell会把所有文件名拼接成一条参数命令大概率直接崩溃。这种情况需要改用?精确定位数量/usr/bin/ca?只精确匹配两个字符再加一个任意字符命中面小很多。或者用字符集/usr/bin/c[au][rt]精确控制每一位。第三种情况WAF做了语义还原。部分WAF在收到请求后会对%0a做解码并对${IFS}做变量模拟导致换行和变量拼接双双失效。这种情况不能只靠单一工具绕了得考虑利用时间延迟判断命令是否执行或利用DNS查询外带数据但这些超出了本文范围以后再单独开篇。第四种情况命令参数位置导致通配符无法展开。例如目标的命令拼接是ping -c 4 你的输入而你输入的参数在最后一个位置。此时如果你提交的是*Shell会把当前目录下所有文件名都填进来当参数没法控制。这种情况可以考虑先在输入里把命令分隔符打通再做二次利用。5.2 一个容易忽视的辅助技巧利用Pinpoint说完失效原因分享一个我常用但看到很多人不太会用的技巧利用命令本身作为目录探测工具。当你不知道目标系统的目录结构时可以利用ls命令配合通配符让目标自己“报名字”。比如构造/?disk/tmp; l?st${IFS}/${IFS}b*n这样的Payload注意这里l?st可以匹配ls或者某个名字相近的命令如果命令成功执行返回的结果自然把目标目录下的文件列表带出来。之后你就有了文件清单再针对性地构造第二次、第三次Payload命中率大幅提升。本质上这就是“信息收集—确定目标—精准打击”的思路在命令执行漏洞利用上的具体化。很多新手失败不是Payload不够多而是对目标环境了解太少连当前目录下有什么文件都没搞清楚就去猜cat flag失败是理所当然的。5.3 短命令场景的特殊处理还有一种特殊情况命令执行点可能只是一个回显型接口比如把参数作为外部程序的参数执行但输出受限。这种情况下你构造的通配符Paylaod能不能生效往往取决于回显本身的内容。如果回显总是被截断那就优先考虑写文件型的Payload利用命令把结果写入到Web目录下的一个文件里再通过另一个HTTP请求读取。类似地如果命令行需要交互通配符绕过是无法直接完成交互的。这种情况需要借助已经执行成功的命令来建立一个更方便的执行通道通常思路是先下载一个反向工具或写入一个WebShell。但这类操作涉及的使用方式千差万别而且合规风险很高这里就不展开具体操作了。6. 防御视角从攻到防的关键加固措施6.1 过滤规则不是安全边界在讲具体防御措施前先说一个我踩过坑后的血泪经验单纯依赖输入过滤来防御命令注入本质上是在和攻击者玩猫鼠游戏。今天补了cat的过滤明天攻击者用c\at绕过今天补了反斜杠明天还有变量拼接今天全部补上后天还有通配符。所以真正的防线必须前移到“如何避免用户输入进入命令解释器”。这一条是所有防御措施的大前提。如果你的系统架构已经允许用户的原始输入直接拼接到Shell命令里那么任何过滤手段都只是降低风险不等于消除风险。6.2 代码层的正确写法从代码层面修复命令注入最稳妥的是两条路。第一条是彻底的“不要用Shell执行”。比如在Python里不要用os.system或者os.popen改成subprocess.run并传入参数列表不让Shell介入解释。subprocess.run([df, -h, user_input])中的user_input会被当作df的独立参数而不是Shell命令的一部分。这条说完很多人会问那如果业务必须用Shell呢比如要用管道、重定向、通配符展开这些Shell能力。这种时候没有银弹只能做白名单校验。只允许输入匹配预定义的安全格式比如IP地址、数字、纯文件名格式之外的一律拒绝。在PHP场景里必须避免使用eval、system、exec、shell_exec、等危险函数或者在使用前进行严格的参数校验。在Java场景里优先使用ProcessBuilder传入字符串数组避免Shell解释。工欲善其事必先利其器这些是代码审计和研发自测的底线要求。6.3 拦截规则如何设计才算合理如果确实需要在应用层做输出过滤或输入过滤比如临时热修、WAF规则应急那么设计规则时要有几个原则第一不要只匹配明文命令。规则要覆盖常见的编码形式和通配符形式URL编码、Unicode编码、十六进制、反斜杠转义、变量拼接、通配符插值。一个规则里出现cat的同时最好也出现c[a-z]at、c\at、c%61t、${IFS}等变体。但这么做也容易产生误拦所以要有配套的放行机制。第二要在命令到达Shell之前做内容解码后的二次检查。比如请求先经过一次URL解码检查一次到后端又可能被框架二次解码再检查一次。很多绕过就是利用了“过滤时看到的和解码后执行的不是同一个字符串”这个时间差。第三要对执行结果设置返回限制。即使命令被执行了如果回显很小或者只有状态码攻击者拿不到输出数据利用难度会大幅上升。可考虑关闭命令回显、只保留成功/失败状态码。6.4 纵深防御的最后几条防线在业务无法快速迭代代码的时候通过系统层加固来兜底是我在应急响应中反复推荐的方案。降低Web服务进程的权限绝对不能用root或者管理员权限运行。开启SELinux或者AppArmor限制进程能执行的二进制文件范围。对关键系统命令做别名或白名单包装。限制Web服务可以访问的目录禁止执行/tmp、/var/www/html等目录下的文件。开启审计日志记录命令执行类系统调用便于事后追溯。有条件时把命令执行功能迁移到独立的沙箱容器中与核心业务网络隔离。这些措施不能阻止攻击者执行第一条命令但能极大延长攻击链路把“拿下服务器”变成“看了两眼目录就走”这是实际对抗中非常常见的分水岭。7. 实际项目中的踩坑记录与排查技巧7.1 踩坑记录匹配多文件导致全部命令失效先说最典型的坑。某次在测试一个老系统的命令执行点时我用/?disk/tmp; /usr/bin/c*${IFS}/etc/passwd来做注入结果不仅cat没执行成功连原本应该正常执行的df输出都丢了。排查发现原因在于/usr/bin目录下同时存在cat、calendar、catch、catman等一堆以c开头的命令c*把所有匹配项都展开成参数最后传给cat的命令行变成了一堆文件路径直接报错。这个问题的解法有两个方向。方向一是缩小通配范围换成/usr/bin/ca?这样只匹配cat、cal如果有、cap如果有等恰好三位且以ca开头的命令命中面小很多。方向二是用字符集精确替代/usr/bin/c[at]匹配到的是ca和ct两个文件不一定命中目标。所以最佳选择往往是用?加路径限制先探测目标目录下与该模式匹配的文件到底有几个再做调整。还有一个小技巧是如果匹配到多个文件导致报错报错信息往往会列出“参数过多”或者“无法打开”的文件名。这些报错信息本身就是Banner信息可以反向利用来获取目录列表。7.2 踩坑记录${IFS}在某些位置不生效另一个常见的问题是${IFS}在部分命令的中间位置不生效。举例来说cat${IFS}/etc/passwd展开后是cat /etc/passwd正常。但如果你把它放在管道符后面比如ls${IFS}./|${IFS}cat${IFS}/etc/passwd某些精简版Shell对${IFS}的展开会有兼容性问题。实测中Bash完全没问题Dash在部分场景下会有细微差异。解决方式也很简单放弃${IFS}在这个场景的使用改用Tab字符。Tab字符在Shell中同样是命令行的合法分隔符而且很多过滤规则不会检查Tab尤其是只按空格切割输入的情况。在HTTP请求中Tab可以表示为%09。实测效果非常稳定。如果Tab和${IFS}都被过滤还有最后的选择利用参数扩展拼接。构造$IFS$9其中$9是第九个位置参数正常Shell环境下它是空的利用它作为变量结束边界有时能规避过滤对$IFS的精确匹配。这个技巧对Bash有效对Sh的兼容性稍差需要现场验证。7.3 踩坑记录通配符绕过成功但命令输出被截断命令执行成功不等于拿到了完整输出很多实战场景下命令回显只返回前几行或者部分内容。出现这种情况首先要确认是因为过滤规则截断了回显还是Web层做了输出长度限制还是后端仅返回部分日志。如果输出被截断一个通用的处理思路是利用命令本身能力缩小输出范围或者把输出变成更容易回显的形式。比如cat /etc/passwd | cut -c1-30但这里管道符可能也被过滤那就换成head -c 30 /etc/passwd配合通配符做命令名绕过。或者干脆用grep定位到指定行号再输出sed -n 3p /etc/passwd。如果连grep、sed这样的命令也被拦最简单的办法是利用过滤规则不拦的关键字构造通配符名称比如s?d、gr?p再配合${IFS}完成参数注入。最终目标是把回显数据压缩到最小可读范围而不是贪多求全。7.4 问题排查速查表现场现象可能原因优先排查方式参考方案空格被拦且命令执行失败过滤规则拦空格换${IFS}、Tab、花括号综合使用多种替代分隔符cat被拦黑名单精确匹配换?、[...]、\转义通配符插入、变量拼接*匹配到多个文件环境文件较多换?或字符集缩小范围c[au]t精确定位命令执行无输出回显被截断用head、grep、sed精简输出换用外带方式DNS/HTTP命令执行不了也不报错语义过滤拦截检查是否触发二次解码叠加变量与通配符变形注入分隔符;被拦黑名单包含分隔符试%0a、$()、换行换行符分离命令全盘过滤但命令点可用过滤规则有逻辑漏洞逐字符边界探测构造不在规则语义内的Payload这个表是我每次做此类测试前的自查清单你完全可以照抄到自己项目里用。7.5 一个值得单独说说的技巧命令执行的响应时间探测有时候目标系统配置了命令回显关闭所有的命令执行结果都不会返回到页面这种情况下怎么判断命令是否执行成功答案是利用时间差。比如构造127.0.0.1 sleep 5如果页面等待了5秒再返回说明命令成功执行了。这个技巧在探测阶段的价值非常大尤其在无法确认过滤器到底拦截了什么的时候时间差能帮你判断一个Payload是否真正到达了Shell。更进阶的用法是结合DNS外带。命令成功执行后触发一次DNS解析请求让目标服务器返回一个可控域名通过检查DNS日志确认命令是否执行。虽然这个方法依赖外部基础设施但在实战中面对较高级的过滤规则时它往往是最可靠的验证手段之一。这里不展开讲具体搭建过程但思路本身值得你在防御设计时警惕即使页面没有任何回显攻击者仍然可能通过时间差和网络请求确认漏洞是否可利用。8. 我的实际体会与几条扩展思考做了这么多年的安全测试和应急响应我最大的感受是命令执行漏洞之所以高危不是因为Shell命令本身有多难防而是因为它总是以各种意想不到的方式出现在业务逻辑里。很多系统的过滤规则写得很努力但面对通配符这种“发生在Shell内部”的展开机制时往往只能眼睁睁看着防线被拆穿。这里想用最后一点篇幅分享三个扩展思考给正在做防护的同行参考。第一个思考是关于LLM与过滤规则的结合。现在的WAF和代码扫描器大多还是基于正则和语义规则来做命令注入检测但我在实际测试中发现规则再长也有边界而通配符展开的变体几乎是无限的。如果能引入大型语言模型对输入做意图还原在检测阶段模拟Shell展开也许能显著提高拦截率。当然这个方案的误报问题很严重部署成本也高短期内很难替代传统规则。第二个思考是关于系统命令的现代化改造。既然通配符展开是Shell的机制那么能减少Shell使用的系统设计就是更安全的设计。比如在很多云原生场景中业务容器已经不再内置完整的Bash而只提供静态编译的二进制可执行文件。这种方式下攻击者即使拿到了命令执行点能够利用的系统命令也大大减少很多通配符绕过技术会失去用武之地。第三个思考是给防御方的建议在写过滤规则前先模拟攻击者做一轮完整的绕过测试。我见过太多的规则写的时候觉得无懈可击但自己动手绕过一次就发现全是漏洞。所以如果你负责安全规则建设建议自己也搭建一个测试环境把文章里提到的几种变形逐一验证一遍。只有亲自动手绕一次才知道你写的规则在实战面前到底有多脆弱。最后给真正在做攻防对抗的同行留一句通配符绕过只是命令注入绕过一个很小的切面它背后隐藏的“Shell语义解析”问题远比几个Payload重要。理解机制比记住Payload更能让你走得更远。