Security

What is SQL Injection (CWE-89)?

SQL Injection (CWE-89) lets attackers read, modify, or delete database data via unsanitized queries. See real vulnerable/secure code and the fix.

SP
Shreya Pillai July 27, 2026 7 min read Security
AI-friendly summary

What it is: SQL Injection (CWE-89) is a type of injection vulnerability that occurs when an application constructs a SQL query using untrusted input without neutralizing SQL syntax elements.

Why it matters: A successful attack can expose, modify, or delete an entire database, and in some configurations even lead to code execution on the database server — MITRE rates this High likelihood of exploit.

How to fix it: Use parameterized queries or prepared statements for every query involving variable data, never string concatenation.

TL;DR: SQL Injection lets an attacker manipulate database queries by injecting unescaped SQL syntax through user input; the fix is parameterized queries or prepared statements, never string concatenation into SQL.

Field Value
CWE ID CWE-89
OWASP Category A05:2025 - Injection
CAPEC CAPEC-108, CAPEC-109, CAPEC-110, CAPEC-470, CAPEC-66, CAPEC-7
Typical Severity Critical
Affected Technologies Any application backed by a SQL database
Detection Difficulty Easy
Last Updated 2026-07-27

What is SQL Injection?

Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’) (CWE-89) is a type of injection vulnerability that occurs when a product constructs all or part of a SQL command using externally-influenced input, but does not neutralize special elements that could modify the intended SQL command. As defined by the MITRE Corporation under CWE-89, and classified by the OWASP Foundation under A05:2025 - Injection, this weakness has a High likelihood of exploit and remains one of the most consequential vulnerability classes in web application security.

Quick Summary

SQL Injection turns any query-backed feature into a potential window onto the entire database, not just the records that feature was meant to return. Because SQL syntax and application data share the same string in a naive implementation, a single unescaped quote character can be enough to change what the database actually executes — and because the technique is decades old and extensively documented, both attackers and automated scanners find it quickly.

Jump to: Quick Summary · SQL Injection Overview · How SQL Injection Works · Business Impact of SQL Injection · SQL Injection Attack Scenario · How to Detect SQL Injection · How to Fix SQL Injection · Framework-Specific Fixes for SQL Injection · How to Ask AI to Check Your Code for SQL Injection · SQL Injection Best Practices Checklist · SQL Injection FAQ · Vulnerabilities Related to SQL Injection · References · Scan Your Own Site

SQL Injection Overview

What: An application builds a SQL query string from untrusted input without neutralizing SQL-meaningful characters, letting an attacker alter the query’s logic.

Why it matters: Successful exploitation typically grants read/write access to the entire database, not just the data the vulnerable feature was meant to expose.

Where it occurs: Any feature that builds a SQL query using string concatenation instead of parameterization — search, login, filtering, reporting.

Who is affected: Applications that build SQL queries by concatenating user input directly into the query string.

Who is NOT affected: Applications using parameterized queries, prepared statements, or a properly-used ORM throughout.

How SQL Injection Works

Root Cause

The application concatenates untrusted input directly into a SQL query string, without using parameterization to separate the data from the query’s own syntax.

Attack Flow

  1. The attacker identifies an input that reaches a SQL query (a login form, search box, or filter parameter).
  2. The attacker submits a value containing SQL syntax, e.g. ' OR '1'='1.
  3. The application concatenates this directly into the query string.
  4. The database parses the injected syntax as part of the query’s actual logic, not as literal data.
  5. The query returns data or performs an action the attacker was never authorized to trigger.

Prerequisites to Exploit

  • Untrusted input reaches a SQL query without parameterization.
  • The application concatenates that input directly into the query string.
  • The database user account the application uses has meaningful privileges the attacker wants to leverage.

Vulnerable Code

def get_user(username, password):
    query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
    return db.execute(query)

Both username and password are concatenated directly into the query, so a username value of admin' -- comments out the password check entirely, logging the attacker in as admin with no valid password required.

Secure Code

def get_user(username, password):
    query = "SELECT * FROM users WHERE username = ? AND password = ?"
    return db.execute(query, (username, password))

The parameterized query separates the SQL syntax from the data at the driver level, so the database always treats username and password as literal values, regardless of what characters they contain.

Business Impact of SQL Injection

Confidentiality: Attackers may read sensitive application data, including credentials, personal information, and business records stored in the database.

Integrity: Attackers may modify or delete data, including tampering with financial records or application logic stored in the database.

Authentication: Attackers may bypass login checks entirely or assume another user’s identity if authentication logic is built on vulnerable queries.

Access Control: Attackers may modify authorization data stored in the database, escalating their own privileges.

  • Full database compromise, often extending to code execution on the database server in vulnerable configurations
  • Regulatory and reputational damage following any confirmed data breach — SQL Injection breaches are among the most costly and public

SQL Injection Attack Scenario

  1. An attacker finds a login form and submits admin' -- as the username with any password.
  2. The concatenated query becomes SELECT * FROM users WHERE username = 'admin' --' AND password = '...', and the -- comments out the password check.
  3. The database returns the admin user’s row, and the application logs the attacker in as an administrator.
  4. From the admin panel, the attacker discovers additional injectable parameters and uses UNION-based injection to dump the entire users table, including password hashes.

How to Detect SQL Injection

Manual Testing

  • Identify every input that reaches a SQL query, directly or indirectly.
  • Submit a single quote and observe whether the application returns a database error or altered behavior.
  • Test boolean-based payloads (' OR '1'='1, ' OR '1'='2) and confirm whether results change accordingly.

Automated Scanners (SAST / DAST)

Static analysis can flag SQL query strings built via concatenation with variables directly in source, while dynamic testing with real injection payloads confirms whether the live application’s database actually executes injected syntax.

PenScan Detection

PenScan’s scanner engines actively test every reachable input for SQL injection using real, safe detection payloads across common database engines (MySQL, PostgreSQL, MSSQL, and others).

False Positive Guidance

An input field that reaches the database only through a parameterized query or ORM method is not vulnerable even if it superficially resembles an injectable sink — confirm the actual query-construction method used, not just proximity to a database call.

How to Fix SQL Injection

  • Use parameterized queries or prepared statements for every query that includes variable data.
  • Use a properly-configured ORM, which builds parameterized queries automatically in the common case.
  • Apply least-privilege database accounts so a successful injection has limited blast radius.
  • Ensure error messages don’t reveal SQL query structure, which can help attackers refine an attack.

Framework-Specific Fixes for SQL Injection

  • Java: use PreparedStatement with bound parameters, or a persistence layer like Hibernate/JPA used correctly (avoiding raw HQL/JPQL string concatenation).
  • Node.js: use parameterized queries via your database driver (? or $1 placeholders), never template-literal string building of SQL.
  • Python/Django: use the Django ORM, or parameterized cursor.execute(query, params) calls — never f-string or .format() query building.
  • PHP: use PDO prepared statements with bound parameters instead of directly interpolating variables into query strings.

How to Ask AI to Check Your Code for SQL Injection

Copy-paste prompt

Review the following [language] code block for potential CWE-89 SQL Injection vulnerabilities and rewrite it using parameterized queries or prepared statements instead of string concatenation: [paste code here]

SQL Injection Best Practices Checklist

✅ Use parameterized queries or prepared statements for all variable data in SQL ✅ Use a properly-configured ORM rather than hand-built query strings ✅ Apply least-privilege database accounts to limit the blast radius of any injection ✅ Avoid revealing SQL query structure in error messages

SQL Injection FAQ

How does SQL Injection let an attacker read an entire database?

When user input is concatenated directly into a SQL query string, an attacker can inject SQL syntax like “ OR ‘1’=’1” that changes the query’s logic, or use UNION-based techniques to append entirely separate queries that return data from other tables.

How is SQL Injection different from OS Command Injection?

Both are concrete instances of the same root weakness (CWE-75/CWE-74) — SQL Injection targets a database engine’s query language specifically, while OS Command Injection targets a shell; the injection mechanism and impact differ, but the underlying mistake (unparameterized string concatenation) is the same.

How likely is SQL Injection to be exploited according to MITRE?

MITRE rates the likelihood of exploit for this weakness as High — it is one of the most well-documented, widely-automated attack classes, with mature tooling on both the offensive and defensive sides.

How do I detect SQL Injection in my own application?

Identify every input that reaches a SQL query, and test with characters like a single quote to see whether the application returns a database error or altered results, indicating the input reached the query unescaped.

How do I fix SQL Injection without breaking legitimate queries?

Use parameterized queries or prepared statements for every query that includes any variable data — the database driver handles quoting and escaping automatically, so legitimate values like “O’Reilly” work correctly without manual escaping.

How does an ORM help prevent SQL Injection?

A properly-used ORM (like Hibernate, SQLAlchemy, or Django’s ORM) builds parameterized queries automatically behind the scenes, removing the need for developers to hand-write SQL string concatenation in most cases — though raw/custom query methods can still reintroduce the vulnerability if misused.

How can PenScan help find SQL Injection?

PenScan actively tests every input reachable by the scanner for SQL injection using real, safe detection payloads across common database engines.

CWE Name Relationship
CWE-943 Improper Neutralization of Special Elements in Data Query Logic ChildOf
CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component (‘Injection’) ChildOf

References

Scan Your Own Site

Manual code review catches what you know to look for. An automated scan catches what you didn’t. Scan your own website using PenScan to find SQL Injection and other risks before an attacker does.