SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration
SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration

All Entries

Category Injection
Typical Severity Critical
OWASP A03:2021 – Injection
CWE CWE-89: Improper Neutralization of Special Elements used in an SQL Command
Also known as SQLi, SQL Injection Attack, Database Injection
Affected systems Web applications, APIs, and backend services that construct SQL queries using user-supplied input; any SQL-based RDBMS (MySQL, PostgreSQL, MSSQL, Oracle, SQLite)
Common attack vectors HTTP request parameters, form fields, URL path segments, cookies, HTTP headers (User-Agent, Referer, X-Forwarded-For)

Overview

SQL Injection (SQLi) is a code injection technique in which an attacker inserts or "injects" malicious SQL statements into an input field or parameter that is subsequently passed to a backend SQL database for execution. When an application constructs SQL queries by concatenating or interpolating user-supplied data without proper validation or escaping, an attacker can alter the intended query structure, bypassing authentication, extracting sensitive data, modifying or deleting records, and in some configurations executing operating-system commands.

SQL Injection has consistently ranked among the most critical web application vulnerabilities for over two decades and remains the top entry in OWASP's Injection category (A03:2021). It is classified under CWE-89 by MITRE.

How it works

The root cause is the failure to treat user input as data rather than executable code. When a web application dynamically constructs a SQL query using string concatenation, an attacker can supply input containing SQL metacharacters (single quotes, double dashes, semicolons, etc.) to alter the query's syntax and semantics.

Classic example (authentication bypass):

-- Intended query:
SELECT * FROM users WHERE username = 'alice' AND password = 'secret';

-- Attacker supplies username: ' OR '1'='1' --
-- Resulting query:
SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = '...';
-- The remainder is commented out; the condition is always true.

SQLi manifests in several distinct forms:

  • In-band SQLi (Classic): Data is extracted through the same channel used to inject the payload. Subdivided into error-based (leveraging database error messages to reveal information) and union-based (appending a UNION SELECT to retrieve data from other tables).
  • Blind SQLi: The application does not return query results or error messages directly. Attackers infer information from application behavior. Boolean-based blind SQLi uses true/false conditions to exfiltrate data one bit at a time; time-based blind SQLi uses conditional time delays (e.g., SLEEP() or WAITFOR DELAY) to infer results.
  • Out-of-band SQLi: Data is exfiltrated through a separate channel, such as DNS or HTTP requests triggered by database functions (e.g., xp_cmdshell on MSSQL, UTL_HTTP on Oracle). Requires specific database features and network egress permissions.
  • Second-order (Stored) SQLi: Malicious input is stored in the database and later retrieved and used in a SQL query without re-sanitization, creating a deferred injection point.

The severity escalates further when the database account has elevated privileges: attackers may read arbitrary files (LOAD_FILE() in MySQL), write files to the filesystem (INTO OUTFILE), or execute OS commands (xp_cmdshell in MSSQL), potentially achieving full server compromise.

Business impact

A successful SQL Injection attack can have severe, multi-dimensional consequences:

  • Data breach: Exfiltration of personally identifiable information (PII), credentials, payment card data, health records, and proprietary business data — triggering breach notification obligations under GDPR, HIPAA, PCI DSS, and similar regulations.
  • Authentication bypass: Attackers can log in as any user, including administrators, without knowing passwords.
  • Data integrity loss: Records can be modified or deleted, corrupting application state and business processes.
  • Service disruption: Dropping tables or corrupting the database schema causes application downtime.
  • Full server compromise: On misconfigured databases, OS-level command execution can lead to complete infrastructure takeover, lateral movement, and ransomware deployment.
  • Regulatory and financial penalties: GDPR fines can reach €20 million or 4% of global annual turnover; PCI DSS violations may result in card scheme fines and loss of payment processing rights.
  • Reputational damage: Public disclosure of a breach erodes customer trust and can cause lasting revenue loss.

How to fix it

  1. Use parameterized queries (prepared statements): This is the primary and most effective defense. Separate SQL code from data at the API level so user input is never interpreted as SQL syntax. All major database drivers and ORMs support this pattern.
    -- Vulnerable (string concatenation):
    query = "SELECT * FROM users WHERE username = '" + username + "'";
    
    -- Safe (parameterized):
    query = "SELECT * FROM users WHERE username = ?";
    preparedStatement.setString(1, username);
  2. Use a well-maintained ORM or query builder: Frameworks such as Hibernate, SQLAlchemy, ActiveRecord, and Entity Framework use parameterized queries internally. Avoid raw query construction even within ORMs (e.g., avoid raw() or execute() with string interpolation).
  3. Apply strict input validation: Validate all user-supplied data against an allowlist of expected type, format, length, and range. Reject inputs that do not conform. This is a defense-in-depth measure, not a substitute for parameterized queries.
  4. Implement least-privilege database accounts: Application database accounts should have only the permissions required for their function (SELECT, INSERT, UPDATE on specific tables). Never use the DBA or root account for application queries. Deny FILE and EXECUTE privileges unless strictly required.
  5. Escape user input as a last resort: If parameterized queries cannot be used (e.g., dynamic table or column names), use the database driver's native escaping function — but this approach is error-prone and should be avoided where possible.
  6. Enable a Web Application Firewall (WAF): A WAF can detect and block known SQLi patterns in transit. This is a supplementary control, not a replacement for secure coding practices, as WAFs can be bypassed.
  7. Suppress detailed error messages: Configure the application to return generic error pages to end users. Never expose raw SQL error messages, stack traces, or query details in HTTP responses.
  8. Conduct regular security testing: Include SQL Injection testing in SAST (static analysis), DAST (dynamic analysis), and manual penetration testing as part of the SDLC. Sensagraph automatically detects SQL Injection vulnerabilities through continuous scanning.
  9. Keep database software patched: Apply vendor security patches promptly to reduce exposure to known database engine vulnerabilities that may amplify SQLi impact.

References

Frequently asked questions

In classic (in-band) SQL Injection, the attacker can directly observe query results or error messages in the HTTP response. In Blind SQL Injection, the application does not return data or errors directly; the attacker must infer information indirectly — either by observing differences in application behavior based on true/false conditions (boolean-based blind), or by measuring response time delays triggered by conditional database functions (time-based blind).

Parameterized queries (prepared statements) are the most reliable primary control and prevent injection in query values. However, they cannot parameterize structural SQL elements such as table names, column names, or ORDER BY clauses. When dynamic structural elements are required, use a strict allowlist of permitted identifiers and map user input to them — never interpolate user input directly into those positions.

No. WAFs can detect and block many known SQLi signatures in transit, providing a useful supplementary layer of defense. However, WAF rules can be bypassed using encoding tricks, unusual syntax, or novel payloads. WAFs do not address the underlying code vulnerability and should not replace secure development practices such as parameterized queries.

In first-order SQL Injection, malicious input is used in a SQL query immediately upon submission. In second-order (stored) SQL Injection, the malicious input is stored in the database and appears benign on entry, but is later retrieved by the application and used in a SQL query without re-sanitization. This makes it harder to detect because the injection point and the exploitation point are separated in time and code path.

All relational database management systems that interpret SQL — including MySQL, PostgreSQL, Microsoft SQL Server, Oracle Database, SQLite, IBM Db2, and MariaDB — are susceptible to SQL Injection if the application fails to properly separate code from data. The specific syntax of payloads varies between DBMS vendors, but the underlying vulnerability class is universal.