Sharing notes from my ongoing learning journey — what I build, break and understand along the way.
OWASP Top 10 – A03: Injection
OWASP Top 10 – A03: Injection
What Is Injection?
Injection is a broad class of attack where untrusted data is sent to an interpreter (such as a database, command line, or XML parser) as part of a command or query. The attacker’s hostile data tricks the interpreter into executing malicious commands, accessing unauthorized data, or even compromising the system entirely.
In simple terms: The application “blindly trusts” user input and ends up executing it as code.
Why Is Injection Dangerous?
- Attackers can steal, modify, or delete data.
- It can lead to full system compromise.
- Some injections require no authentication.
- Often result in data breaches, defacements, or privilege escalation.
- Common in applications with poor input validation and dynamic query building.
Types of Injection
1. SQL Injection (SQLi) – The Classic
Injecting malicious SQL code into a query.
Example:
SELECT * FROM users WHERE username = 'admin' AND password = '1234';
Malicious input:
' OR '1'='1
Final query:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '1234';
This returns all users — attacker logs in as admin without knowing the password.
2. Command Injection
Running shell/system commands with user input.
Example:
os.system("ping " + user_input)
Input:
8.8.8.8 && rm -rf /
Final command:
ping 8.8.8.8 && rm -rf /
3. LDAP Injection
Attacking Lightweight Directory Access Protocol queries.
Example:
(&(user=admin)(password=secret))
Injected input:
*)(|(user=*))
Results in bypassing authentication with wildcard logic.
4. XPath Injection
Manipulating XML data queries.
5. NoSQL Injection
Attacking databases like MongoDB via JSON-based queries.
Example:
db.users.find({ username: input })
Input:
{ "$ne": null }
This returns all users.
Root Causes of Injection
- Unsanitized or unvalidated input
- Dynamically built queries with user input
- Misuse of interpreters or evaluators (e.g.,
eval()
) - Weak separation between code and data
- Lack of parameterized APIs
How to Prevent Injection
1. Use Parameterized Queries (Prepared Statements)
Do not concatenate user input directly into queries.
Bad:
"SELECT * FROM users WHERE username = '" + user + "'"
Good (Python):
cursor.execute("SELECT * FROM users WHERE username = ?", (user,))
Good (PHP – PDO):
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :user");
$stmt->execute(['user' => $user]);
2. Escape Special Characters
When using non-parameterized interfaces (legacy code), escape dangerous characters based on context:
- SQL:
'
,--
,;
- HTML:
<
,>
,&
- Shell:
|
,&
,;
But remember: escaping is not a substitute for safe coding.
3. Input Validation & Whitelisting
- Validate input types and patterns strictly.
- Use whitelisting over blacklisting.
Examples:
- Username: only letters and digits
- Email: regex-validated
- Price: must be numeric and positive
4. Avoid Dangerous Functions
- Don’t use
eval()
,exec()
,system()
with raw input. - Avoid unsanitized templating engines.
5. Use ORM or High-Level APIs
Object-Relational Mapping tools (like SQLAlchemy, Django ORM, Sequelize) abstract SQL queries and reduce injection risk.
6. Error Handling
- Don’t show raw error messages to users.
- Log detailed errors internally for developers.
Don’t:
{"error": "SQL syntax error near 'admin' line 1"}
Do:
{"error": "An unexpected error occurred."}
Testing Tools for Injection Vulnerabilities
- Burp Suite – Manual payload testing
- SQLMap – Automated SQL injection scanner
- ZAP Proxy – Open-source security scanner
- NoSQLMap – For MongoDB and NoSQL DBs
- Nmap NSE Scripts – Has modules for SQLi detection
Cheat Sheet of Common Payloads
' OR '1'='1
' OR 1=1 --
' UNION SELECT null, username, password FROM users --
" | ls -la
"; DROP TABLE users; --
Use payloads appropriate to context (SQL, shell, HTML, LDAP, etc.).
Injection attacks remain a top threat because:
- They’re easy to exploit
- They have high impact
- They often stem from lazy or outdated coding practices
To protect your apps:
- Use parameterized queries
- Validate and sanitize everything
- Never trust user input — ever.