Command Injection Filter Bypass Using Character Encoding: Techniques from PayloadsAllTheThings

Command injection filter bypass using character encoding exploits shell variable expansion, hex sequences, and Unicode normalization to represent blocked characters in alternative formats that resolve to malicious commands at runtime.

Web applications typically mitigate command injection by blacklisting dangerous characters like spaces, quotes, and path separators. However, the PayloadsAllTheThings repository by swisskyrepo demonstrates how attackers leverage encoding transformations to evade these naive filters without altering the final command semantics.

How Encoding-Based Filter Bypasses Work

When applications filter input at the perimeter, they often scan for literal ASCII representations of shell metacharacters. Attackers circumvent these defenses by submitting encoded equivalents that pass the filter but are decoded or expanded by the shell after the validation stage.

Variable Substitution with ${IFS}

The shell expands variables before executing commands, making this the most reliable bypass technique. In Command Injection/README.md (lines 45–50), the repository documents using ${IFS} (Internal Field Separator) and ${HOME:0:1} to reconstruct blocked characters dynamically.


# Filter blocks literal spaces: "cat /etc/passwd" → blocked

# Bypass using shell variable expansion:

cat${IFS}/etc${IFS}passwd

${IFS} evaluates to a space at runtime, reassembling the command only after the filter has processed the input.

Hex Encoding Sequences

Hex-encoded characters bypass filters that scan for literal path separators or command delimiters. According to lines 62–78 of Command Injection/README.md, representing /etc/passwd as hex sequences allows the payload to pass alphanumeric-only filters.


# Hex representation of "/etc/passwd"

payload=$(echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64")
cat $payload

The filter sees only backslashes and hex digits, while echo -e decodes the sequences into the target path before execution.

Unicode Normalization Attacks

Modern shells and libraries automatically normalize Unicode characters to their ASCII canonical forms. As documented in Encoding Transformations/README.md#unicode-normalization, attackers substitute visually identical full-width characters that transform into dangerous metacharacters during processing.


# Filter blocks ASCII single quotes: w'h'o'am'i → blocked

# Use full-width single quote (U+FF07):

w'h'o'am'i

After NFKC normalization, ' (U+FF07) becomes ', allowing command substitution or string termination to occur.

Practical Bypass Implementations

The Command Injection/Intruder/command_exec.txt file contains real-world polyglot payloads combining multiple encoding strategies to work across different quoting contexts.

Polyglot Payload Construction

payload="1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}\";sleep${IFS}9;#${IFS}"

This single payload executes sleep 9 regardless of whether the vulnerable application wraps input in single quotes, double quotes, or no quotes, demonstrating how encoding flexibility defeats context-specific filters.

Reconstructing Blocked Slashes

When applications filter the / character from paths, attackers use substring expansion or alternative encodings:


# Using ${HOME:0:1} to produce "/" without the literal character

cat ${HOME:0:1}etc${HOME:0:1}passwd

Why Character Blacklisting Fails

Relying on literal character filtering fails against encoding bypasses for three fundamental reasons:

  1. Shell expansion occurs post-validation – Variables like ${IFS} are substituted after the filter runs, rendering the check ineffective.
  2. Automatic Unicode normalization – Many runtime environments convert full-width characters (/, ', ") to their ASCII equivalents (/, ', ") before command execution.
  3. Runtime decoding – Hex (\x2f) and URL-encoded (%2f) sequences are decoded by the web server, language runtime, or shell interpreter after passing through the filter.

Summary

  • Variable substitution using ${IFS} and ${HOME:0:1} reconstructs blocked spaces and slashes at runtime.
  • Hex encoding (\x2f\x65\x74\x63) represents paths using only alphanumeric characters and backslashes that bypass pattern matching.
  • Unicode normalization converts full-width quotes and slashes into dangerous ASCII metacharacters after filter processing.
  • The PayloadsAllTheThings repository documents these techniques in Command Injection/README.md and Encoding Transformations/README.md with specific line references to implementation details.
  • Blacklist filters are ineffective against encoding bypasses because shells resolve alternative representations into the same dangerous bytes.

Frequently Asked Questions

What is ${IFS} in command injection attacks?

${IFS} is a shell variable representing the Internal Field Separator, which defaults to whitespace. Attackers use it to inject spaces into commands without typing the literal space character, bypassing filters that block ASCII 0x20. As the shell expands variables before execution, the filter sees cat${IFS}/etc/passwd as safe, while the shell executes cat /etc/passwd.

How does hex encoding bypass command injection filters?

Hex encoding represents characters as \x followed by hexadecimal values (e.g., \x2f for /). Filters scanning for literal slashes or quotes fail to detect these sequences, while the echo -e command or language-specific decoders convert them back to the original dangerous characters at execution time.

Can Unicode characters execute shell commands?

Yes, when applications or shells perform Unicode normalization. Full-width characters like ' (U+FF07) or / (U+FF0F) visually resemble ASCII quotes and slashes but pass through filters blocking the standard versions. During processing, NFKC or NFC normalization transforms these into their ASCII equivalents, enabling command execution or path traversal.

How do you prevent encoding-based command injection?

Prevent these attacks by avoiding shell execution entirely—use language-native APIs instead of system calls. When shell interaction is unavoidable, employ allow-list validation permitting only expected characters, use proper escaping functions like escapeshellarg(), and disable or filter variable expansion syntax (${}, $()) before the shell interpreter receives the input.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →