最近在打 DVWA把 Command Injection 这一关从 Low 到 Impossible 全过了一遍把源码和 payload 都记下来方便以后复习也顺便给同样在打 DVWA 的朋友一个参考。环境说明Windows 11 加 WSL2 里的 Kali 发行版DVWA 用 Docker 跑的镜像是 vulnerables/web-dvwa端口映射到宿主机 8081。难度在 DVWA Security 菜单里手动切换每换一次难度代码就换一套。命令注入是个什么洞这一关的页面功能很简单输入一个 IP后端去 ping 它把结果返回给浏览器。功能本身没什么毛病问题出在后端是怎么拼接这条命令的。Linux shell 里几条命令可以用特殊符号串起来。a b 是 a 执行成功才执行 ba b 是 a、b 都执行不管 a 成败a ; b 是顺序执行a | b 是 a 的输出交给 b 处理。如果用户输入被原样拼进命令字符串这些符号就成了追加任意命令的入口。Low没有任何过滤先看 Low 级别的后端源码页面右下角可以点 View Source 查看。关键就这一行$cmd shell_exec(ping -c 4 . $target);用户输入的 target 变量没经过任何处理直接拼到了 ping 命令后面。输入框里填127.0.0.1 whoami点 Submit 后 ping 会先跑几秒-c 4 是发四个包别急着刷新等它出结果。返回结果里除了 ping 的输出还多了一行 www-data这是容器里跑 Web 服务的用户。到这里命令执行就实锤了。其他几个符号也都能用。127.0.0.1 后面接分号加 whoami 是顺序执行效果一样。后面接单个竖线加 whoami 是管道ping 的输出丢给 whoami最后只剩用户名。后面接两个竖线加 whoami 这个反而看不到结果因为 ping 成功了所以后面不执行。Medium黑名单出现切到 Medium再看源码比 Low 多了两行。$target str_replace( , , $target);$target str_replace( ;, , $target);思路是黑名单把 和 ; 从输入里删掉。但 shell 的命令连接符号不止这两个单个 就没在名单里。填这个照样能通127.0.0.1 ; whoami 和 的区别是 不关心前面的命令是否执行成功直接把后面这条也丢进后台跑。过滤的人大概默认想连命令肯定用 漏了单字符的情况。还有一个比较猥琐的玩法。str_replace 是一次性替换所以可以构造一个删完刚好剩下 的输入127.0.0.1 ; whoami中间的分号被删掉后剩下的正是 最终执行的还是前面那条完整命令。这种绕过方式挺能说明黑名单的脆弱只要替换逻辑有规律就能反着构造。High一个空格的安全边界High 的黑名单升级成了一个数组。$substitutions array( ,; ,| ,- ,$ ,( ,) , ,|| ,);乍一看各种符号全堵了好像没路了。但仔细看第三项过滤的是竖线加一个空格不是单独的竖线。也就是说竖线后面只要不跟空格就不会被替换掉。payload注意竖线和 whoami 之间没有空格127.0.0.1|whoami这一关给我的印象挺深。写过滤规则的人大概是想保留 cmd 加空格加竖线加空格加 grep 这种带空格的正常管道用法结果正着用不了歪着用就直接绕过去了。一个空格就是安全边界。Impossible正确答案长什么样Impossible 的代码值得单独贴一段因为它就是这道题的标准修复写法。先用正则校验如果不是标准 IP 格式直接拒绝根本不给拼进命令的机会。校验通过后再用 escapeshellarg 转义把所有特殊字符处理掉再拼进命令。if( !preg_match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, $target) ) {echo Invalid IP format;} else {$cmd shell_exec(ping -c 4 . escapeshellarg($target));}白名单加转义两道保险。对比前三关的 str_replace能明显感觉到思路上的差距。小结三个难度的差异本质就是过滤强度的差异。Low 无过滤直接 或竖线就能执行任意命令。Medium 用 str_replace 删 和分号单个 就能绕或者用 ; 这种组合还原。High 黑名单更全但竖线加空格这一项过滤规则里藏了个细节不带空格的竖线逃过一劫。修复思路从 Impossible 里已经能看出来了。第一输入做白名单校验格式、长度、字符集都卡死。第二实在要拼进命令用 escapeshellarg 或 escapeshellcmd 转义。第三更根本的做法是能不拼就不拼改用参数化的 API。黑名单是堵白名单是筛。堵永远堵不全筛才筛得干净。这一关打完对这句话的理解会比看十篇科普都深。