HTTP Header Command Injection
HTTP header command injection is an OS command-injection variant in which an application reads a client-controlled HTTP request header — X-Forwarded-For, User-Agent, Client-IP, Referer, Accept-Language — and concatenates it, unsanitized, into a shell command (typically via PHP’s system(), exec(), shell_exec(), or backticks). The header value then breaks out of its intended argument position with shell metacharacters (;, &&, |, `, $()) and executes attacker-chosen commands with the web server’s privileges. It maps to CWE-77 (Improper Neutralization of Special Elements used in a Command).
Why headers are the payload carrier
Developers routinely treat request headers as metadata rather than user input, so header values bypass the validation applied to $_GET/$_POST parameters. The classic trigger is an application that needs the “real” client IP and reaches for X-Forwarded-For (which any client can set arbitrarily — see http) and then feeds that value to a network utility:
// firewall.php — the anti-pattern
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
system("sudo iptables -A INPUT -s $ip -j ACCEPT");An attacker supplies:
X-Forwarded-For: 127.0.0.1 -j ACCEPT; sudo cat /root/root.txt ; echoand the shell executes the injected commands between the ; separators. When the wrapped command runs under sudo (a common pattern for firewall/packet-filter management pages), the injection yields root directly.
Real-world instances
- CVE-2016-10322 — Synology Photo Station before 6.3-2958: remote command execution via shell metacharacters in the
X-Forwarded-Forheader passed tophoto/login.php(CVSS 8.8). - CVE-2006-0957 — freeForum static code injection via
X-Forwarded-ForandClient-IPheaders stored into an executable PHP data file. - Web shells — attackers hide command channels in
User-Agent(system($_SERVER['HTTP_USER_AGENT'])) orAccept-Language, the latter evading access-log scrutiny because the header is rarely logged. - CTF/HTB pattern — a
firewall.php-style page withsudoiptables access that concatenatesX-Forwarded-For/Remote-Hostintosystem(), exploited to read/root(HackTheBox Union).
Detection and exploitation notes
- Headers don’t appear in most access logs, so header-channel injection and header-based web shells are quieter than parameter-based equivalents — test them on every input-reflecting endpoint.
- Any header is fair game; prioritize
X-Forwarded-For,Client-IP,User-Agent,Referer,Accept-Language, and customX-*headers the application echoes or logs. - Confirm blind injection with out-of-band callbacks (DNS/HTTP to an interactsh-style listener) when command output isn’t reflected.
- Remember the application may prepend/append fixed arguments — craft metacharacters that leave valid syntax on both sides (
; cmd ; echoneutralizes a trailing suffix).
Defense
- Never pass request data to a shell. Use language-native APIs (PHP’s
Net_IPTables-style libraries, direct netlink/netfilter interfaces) instead ofsystem(). - If a subprocess is unavoidable, use
escapeshellarg()/escapeshellcmd()and an allow-list (e.g., validate IPs withfilter_var($ip, FILTER_VALIDATE_IP)). - Treat all headers as attacker-controlled; apply the same validation as body parameters.
- Drop
NOPASSWDsudo rules for the web-server user, and never let a web page invokesudo iptableswith request-derived arguments.
Sources
- CVE-2016-10322 — Synology Photo Station Command Injection
- CVE-2006-0957 — freeForum Static Code Injection
- Keeping Web Shells Under Cover (Web Shells Part 3) | Acunetix
- HTTP:USER-AGENT-CMD-INJ | Juniper Threat Labs
Related: http, sql-injection-attacks, burp-suite