the_open_door
coffee
ESEN
← Back to index

tar wildcard injection

tar wildcard injection is a classic abuse that shows up when a user can run tar as root (via sudo) over a path containing a wildcard *, for example:

(ALL) NOPASSWD: /usr/bin/tar -czvf /tmp/backup.tar.gz *

The trick is in how the shell expands the *: before launching tar, it replaces the wildcard with the list of files in the current directory. If that directory contains files whose name matches a tar option, those names reach tar as arguments, not as data. tar supports --checkpoint (print a notice every N records) and --checkpoint-action=exec=... (run a command when a checkpoint is reached). Combining them yields command execution:

echo "" > "--checkpoint-action=exec=sh payload.sh"
echo "" > "--checkpoint=1"
echo "/bin/bash" > payload.sh
chmod +x payload.sh
sudo /usr/bin/tar -czvf /tmp/backup.tar.gz *

When the * expands, tar receives --checkpoint=1 and --checkpoint-action=exec=sh payload.sh as if they were options: at the first checkpoint it runs payload.sh, which spawns a shell. Since tar runs as root, that shell is root.

Why it works. The flaw isn't in tar but in the combination of an unbounded wildcard and shell expansion: any file a user controls in the directory becomes an argument. It's the same idea that affects other binaries when passed *.

Other binaries with the same pattern

# rsync -e lets you launch a "remote shell" command
touch ./-e; echo 'sh payload.sh' > './-e sh payload.sh'
sudo rsync -a * root@localhost:/tmp/    # the -e argument slips in and runs the command

# chown/chmod: the --reference flag takes owner/mode from a file we control
touch "--reference=ref"; # ref with chosen owner/mode → chown * applies them to everything

# 7z / zip: -i@... and -x@... read file lists, allowing arbitrary path reads
touch @/etc/shadow; touch ./-op    # 7z filters and reveals contents of files it shouldn't

Requirements

You must be able to create files in the directory the wildcard acts on and have the command actually run from there (the * expands in the cwd). The file name IS the argument: that's why you create empty files named literally --checkpoint=1, etc. If the command pins the path with cd /other, the wildcard expands over that directory, not ours.

How to spot it. The giveaway is a sudo -l allowing tar (or chown, chmod, rsync) over a path with *, or a script/cron that archives a directory with a wildcard. The constant is the unbounded wildcard over a directory where we can create files. When a scheduled task launches it instead of sudo, pspy reveals the exact tar line.

Defence. Don't grant sudo commands with wildcards; pin full paths and arguments (no *); and if you must archive, do it from a wrapper script that controls the directory and file list. Related to sudo escapes (GTFOBins) and other sudoers abuses.

Machines where it's used