SQL injection, commonly shortened to SQLi, is a web application vulnerability that occurs when user-controlled input is allowed to interfere with a database query.

Instead of treating the user's input only as data, a vulnerable application may accidentally allow that input to change the meaning or structure of the SQL command sent to the database.

As a result, an attacker may be able to access information they should not see, alter application behaviour, modify records or, in more serious cases, gain broader database access.

The underlying problem is surprisingly simple:

The application fails to keep SQL instructions separate from user-supplied data.

OWASP explains that SQL injection commonly appears when applications build dynamic database queries using string concatenation together with user input. MITRE classifies the weakness as CWE-89: Improper Neutralization of Special Elements used in an SQL Command.

Therefore, understanding SQL injection is less about memorising attack commands and more about understanding how information moves from a user, through an application, and into a database.

What Is SQL Injection?

SQL injection is a security vulnerability in which externally controlled input can change the intended SQL query executed by an application.

A normal application might receive information such as:

  • a username,
  • a product category,
  • a search term,
  • a customer ID,
  • a date,
  • or a filter.

The application then uses that information to retrieve the appropriate records from a database.

For example, a product page may need to ask a database:

SELECT * FROM products
WHERE category = ?

The ? represents a value supplied separately by the application.

In a properly designed query, the database understands that the supplied value is data, not part of the SQL command itself.

However, problems arise when the application directly combines user input with the SQL statement.

In that situation, specially crafted input may interfere with the surrounding query.

PortSwigger describes SQL injection in similar terms: user-controlled data is incorporated into an SQL query in an unsafe manner, allowing the input to interfere with the structure of the query.

How Does SQL Injection Work?

The easiest way to understand SQL injection is to follow the complete request path.

A database-driven web application generally works like this:

User

Web page or API

Application code

SQL query

Database

Result returned to application

Result displayed to user

Normally, each layer has a clear responsibility.

The user provides information.

The application decides what query should be performed.

Finally, the database executes that predefined query.

SQL injection occurs when those boundaries become blurred.

Step 1: The User Sends Input

Imagine an online store with a category filter.

The user selects:

Laptops

The application receives that value.

At this point, nothing dangerous has happened. User input is a normal part of almost every interactive website.

Step 2: The Application Creates a Database Query

The application needs to retrieve the appropriate products.

Conceptually, the intended query is:

SELECT * FROM products WHERE category = 'Laptops';

The website then displays the matching results.

This is normal application behaviour.

Step 3: The Application Handles the Input Unsafely

The vulnerability appears if the developer builds the query by directly joining SQL code and user input.

Conceptually:

SQL statement + user-controlled text

Instead of:

Fixed SQL statement + separate parameter

This difference is critical.

If the input becomes part of the SQL command itself, specially constructed input may alter the query.

OWASP identifies dynamic queries built using string concatenation and user-supplied input as a typical cause of SQL injection vulnerabilities.

Step 4: The Database Receives the Altered Query

The database does not automatically know which text originally came from:

  • the developer,
  • the web form,
  • the URL,
  • or an API request.

It simply receives an SQL statement.

Therefore, if the application has already mixed user-controlled input into the SQL structure, the database may interpret part of that input as SQL rather than ordinary data.

This is the key point:

The attacker is not necessarily attacking the database directly. The vulnerable application creates and submits the unintended database query on the attacker's behalf.

That distinction makes SQL injection much easier to understand.

Normal Query vs SQL Injection

Normal application behaviourSQL injection vulnerability
User input is treated as dataInput can influence SQL structure
Query logic remains fixedQuery logic may change
Application controls the queryUser input influences the query
Only authorised data should be returnedAdditional data may become accessible
Parameters are separated from SQL codeInput is directly concatenated into SQL

Therefore, the most effective defence is not simply trying to identify every possible malicious word.

Instead, the application should be designed so that user-controlled values cannot become executable SQL syntax in the first place.

Consider a shopping website.

A customer chooses:

Category: Laptops

The application's intended operation is simple:

Return products where category = Laptops

However, suppose the application builds that database request using unsafe string concatenation.

An attacker may submit specially constructed input designed to change the query conditions.

Consequently, instead of returning only laptops, the database might return records that the application did not intend to expose.

PortSwigger describes this type of SQL injection as retrieving hidden data, where injected conditions alter a query so additional database records become visible.

The important point is not the exact attack syntax.

It is the difference in application logic:

Normal behaviour

Input:

Laptops

Purpose:

Show only products in the Laptop category.

Vulnerable behaviour

Input:

Specially crafted database-related input

Possible result:

The application's query condition is altered,
causing additional records to be returned.

Therefore, even a simple product filter can become a security problem if it handles database input incorrectly.

Practical Example 2: Login System

Now consider a login page.

The user enters:

Username
Password

The application should conceptually ask:

Does this username exist
AND
does the supplied password match?

The database query logic must remain fixed.

However, if the username or another value is inserted unsafely into the SQL query, specially constructed input might interfere with those conditions.

Instead of the application checking:

Username matches
AND
Password matches

the query logic might be changed in an unintended way.

PortSwigger refers to this category as subverting application logic.

Again, the important concept is:

SQL injection can transform user input from “information to check” into “input that changes how the check itself works.”

That is why SQL injection can potentially affect authentication as well as ordinary data retrieval.

Where Can SQL Injection Happen?

SQL injection is often associated with login forms.

However, it can occur anywhere user-controlled information reaches a database query.

Possible locations include:

  • search fields,
  • login forms,
  • product filters,
  • URL parameters,
  • API requests,
  • JSON input,
  • XML input,
  • customer IDs,
  • sorting functions,
  • reporting tools,
  • administrative interfaces.

Moreover, SQL injection is not limited to SELECT statements.

Depending on the vulnerable application, SQL queries may involve operations such as:

  • reading data,
  • adding data,
  • updating data,
  • deleting data,
  • sorting results,
  • selecting columns or tables.

PortSwigger notes that SQL injection can occur in different parts of queries, including SELECT, UPDATE, INSERT and other query structures.

Therefore:

SQL injection is not simply a login-page vulnerability. It is a database-query construction problem.

Types of SQL Injection

Different SQL injection vulnerabilities behave differently.

However, they all share the same underlying issue: untrusted data is allowed to interfere with SQL query structure.

TypeHow it worksWhat may reveal the vulnerability
In-band SQL injectionResults return through the normal application responseDatabase output
Error-based SQL injectionDatabase errors expose useful informationError messages
Union-based SQL injectionResults from additional database queries may be combinedUnexpected records
Blind SQL injectionDatabase output is not shown directlyChanges in application behaviour
Time-based blind SQL injectionResponse timing is used to infer conditionsDelayed responses
Second-order SQL injectionInput is stored first and later reused unsafelyVulnerability appears at a later stage

What Is Blind SQL Injection?

Sometimes the application does not display database results or useful error messages.

Nevertheless, a vulnerability may still exist.

The attacker may instead observe differences such as:

  • one page response versus another,
  • whether content appears,
  • whether an error occurs,
  • or how long a response takes.

Therefore, the absence of visible database output does not necessarily mean SQL injection is impossible.

What Is Second-Order SQL Injection?

Second-order SQL injection is particularly important because the dangerous input may not cause a problem immediately.

For example:

Step 1: User submits information.

Step 2: Application safely stores it in the database.

Step 3: Another feature later retrieves that information.

Step 4: The application inserts the stored value into another SQL query unsafely.

At that later stage, the stored information may interfere with the new query.

PortSwigger describes this as second-order or stored SQL injection. Importantly, data that was stored safely should not automatically be considered trustworthy when it is later reused.

This leads to a broader security lesson:

Stored data is not automatically safe data.

What Can SQL Injection Do?

The impact depends on the application, database permissions and the specific vulnerability. Nevertheless, SQL injection may potentially affect confidentiality, integrity and access control.

Possible impactPractical meaning
Read unauthorized dataCustomer, account or business information may be exposed
Bypass application logicRestricted functions may become accessible
Modify database recordsInformation may be changed
Delete informationData integrity or availability may be affected
Discover database structureTable or column information may be exposed
Escalate privilegesMore powerful database permissions may be reached
Broader system impactSerious configurations may expose additional backend functionality

MITRE lists consequences including unauthorized data access, modification, authentication bypass and other forms of database compromise.

However, it is important not to assume that every SQL injection vulnerability automatically gives an attacker complete control of a server.

The actual impact depends heavily on database configuration, application privileges and surrounding security controls.

Why Input Validation Alone Is Not Enough

A common idea is:

"Just block SQL words."

For example, a developer might try to reject particular keywords or characters.

However, this should not be the primary defence.

There are several reasons.

First, databases differ in syntax.

Second, encoding and application behaviour can change how input is interpreted.

Third, legitimate user data may contain punctuation or characters that simplistic filters reject.

Moreover, SQL input may arrive from multiple locations, including APIs, JSON bodies or stored database values.

Therefore, trying to maintain a blacklist of every possible dangerous input is fragile.

OWASP strongly discourages relying primarily on escaping all user-supplied input and recommends parameterized queries instead.

The stronger principle is:

Do not try to recognise every possible SQL injection attack. Build database queries so that user input cannot change their structure.

How to Prevent SQL Injection

SQL injection is highly preventable when developers follow secure database-access practices.

The most important defences are:

  1. parameterized queries,
  2. prepared statements,
  3. allow-list validation where necessary,
  4. least-privilege database access.

1. Use Parameterized Queries and Prepared Statements

This is the most important defence.

With a parameterized query, the SQL structure is defined first.

For example:

SELECT * FROM users
WHERE username = ?

Then the application supplies the username separately.

Conceptually:

SQL code:
SELECT * FROM users WHERE username = ?

Parameter:
customerName

Because the database receives the SQL structure separately from the value, the input is treated as data.

OWASP recommends prepared statements with parameterized queries as its first primary defence against SQL injection.

PortSwigger likewise recommends parameterizing variable data because the query structure has already been defined before the value is supplied.

In simple terms:

Unsafe concept

SQL code + user input = one constructed string

Safer concept

Fixed SQL code
+
separately bound user value

Therefore, the database can distinguish:

code

from

data.

2. Avoid Dynamic SQL String Concatenation

Applications should avoid database code that conceptually looks like:

query = SQL text + userInput

Even if the developer believes the input is harmless, future changes may expose it to untrusted data.

Instead, query parameters should be used wherever the database interface supports them.

This reduces the chance that a new feature later introduces SQL injection accidentally.

3. Use Allow-List Validation Where Parameters Cannot Be Used

Not every part of an SQL query can always be represented as a standard parameter.

For example, an application may allow users to choose:

  • sort by price,
  • sort by name,
  • sort by date.

Instead of inserting arbitrary user input directly into the SQL query, the application can map a limited set of accepted choices.

Conceptually:

Allowed values:

price
name
date

Anything else is rejected.

This is called allow-list validation.

OWASP recommends allow-list validation for cases where bind variables cannot be used directly.

4. Apply Least Privilege

Even secure applications should assume that vulnerabilities may occur.

Therefore, the database account used by the web application should only have permissions required for its function.

For example, a product catalogue that only needs to read product records may not need permission to:

  • delete entire tables,
  • create database users,
  • modify administrative settings.

The principle is:

Application compromised

Database account accessed

Permissions remain limited

Potential damage is reduced

Least privilege does not fix SQL injection.

However, it can reduce the blast radius if another defence fails.

SQL Injection Prevention Comparison

DefenceRecommended?Why
Parameterized queriesYesSeparates SQL code from data
Prepared statementsYesKeeps query structure fixed
Allow-list validationYes, where neededRestricts acceptable dynamic values
Least privilegeYesLimits potential damage
Properly designed stored proceduresCan beSafe when they avoid unsafe dynamic SQL
Manual escapingNot preferredFragile and database-specific
Blocking SQL keywordsNot enoughIncomplete as a primary defence
Web Application FirewallAdditional layerDoes not repair vulnerable application code

Importantly, stored procedures are not automatically safe.

Both OWASP and MITRE note that stored procedures can still become vulnerable if they construct unsafe dynamic SQL internally.

Can a Web Application Firewall Stop SQL Injection?

A Web Application Firewall, or WAF, may detect and block some suspicious requests.

Therefore, it can provide an additional security layer.

However:

A WAF does not fix vulnerable application code.

Rules may miss unusual attack patterns, while applications may change over time.

Consequently, the primary defence should remain secure query construction.

A better security model is:

Parameterized queries
+
Input validation
+
Least privilege
+
Testing
+
Additional monitoring/WAF where appropriate

rather than:

Vulnerable code
+
WAF

SQL Injection vs XSS

SQL injection and Cross-Site Scripting (XSS) are both injection-related vulnerabilities, but they affect different parts of an application.

SQL InjectionCross-Site Scripting
Primarily targets database query handlingPrimarily affects browser-side content
SQL structure is influencedScript/content is injected into a page
Main target is often backend dataMain target is often another user's browser
May expose or modify database recordsMay affect sessions, page behaviour or displayed content
Main defence includes parameterized SQL queriesMain defence includes correct output encoding and safe DOM handling

Therefore:

SQL injection is mainly a server/database query problem, whereas XSS is mainly a browser/content execution problem.

A dedicated XSS guide can explore that distinction in more detail.

How Developers Can Check for SQL Injection Risk

Before deploying a database-driven application, developers should review how user-controlled information reaches the database.

A practical checklist includes:

  • Are database values passed through parameterized queries?
  • Are any SQL statements built using string concatenation?
  • Can URL parameters reach database queries?
  • Can API or JSON values reach SQL statements?
  • Are dynamic table or column names restricted to an allow-list?
  • Are database accounts limited to necessary permissions?
  • Are detailed database errors exposed to users?
  • Are stored values treated as untrusted when reused?
  • Are automated security tests included in development?
  • Is the application regularly reviewed for injection vulnerabilities?

This review should cover more than visible website forms.

APIs and internal application functions can expose the same weakness.

Frequently Asked Questions

1. What is SQL injection in simple terms?

SQL injection is a vulnerability where user-controlled input is allowed to change the SQL query an application sends to its database. Instead of being treated only as data, part of the input may be interpreted as SQL code.

2. How does SQL injection work?

SQL injection usually occurs when an application combines user input directly with an SQL query. If the query is constructed unsafely, specially crafted input may change its intended logic.

3. Is SQL injection still possible today?

Yes. Modern programming frameworks provide safer database interfaces, but SQL injection can still occur when developers build database queries using unsafe dynamic strings or otherwise mix code and data. OWASP continues to include SQL injection under the broader Injection category in its current guidance.

4. Can SQL injection happen without a login form?

Yes. SQL injection can potentially appear in:

  • search fields,
  • URLs,
  • APIs,
  • filters,
  • JSON input,
  • reporting tools,
  • administrative features,
  • or other database-connected functions.

5. What is blind SQL injection?

Blind SQL injection occurs when the application does not directly return database information, but differences in behaviour or response timing can still reveal information about the query result.

6. What is second-order SQL injection?

Second-order SQL injection occurs when user-controlled data is stored first and later used unsafely inside another SQL query. The vulnerability therefore appears at a later stage rather than when the information is initially submitted.

7. What is the best way to prevent SQL injection?

The primary defence is to use parameterized queries or prepared statements, which keep SQL code separate from user-controlled values. OWASP identifies prepared statements with parameterized queries as its first recommended defence.

8. Does input validation prevent SQL injection?

Input validation is useful as an additional defence. However, it should not replace parameterized queries because validating or filtering every possible malicious SQL input is difficult and error-prone.

9. Are stored procedures safe from SQL injection?

They can be safe when implemented correctly. However, stored procedures that build dynamic SQL using untrusted values can still be vulnerable.

Conclusion

SQL injection occurs when an application fails to maintain a clear boundary between:

SQL instructions

and

user-controlled data.

The typical failure path is:

User input
→ Application
→ Unsafe query construction
→ Database executes altered query
→ Unauthorized behaviour or data exposure

Therefore, the strongest prevention strategy is not trying to identify every possible malicious SQL phrase. Instead, applications should be designed so that user-controlled values cannot alter the SQL query structure.

In practice, that means:

  • use parameterized queries,
  • avoid string concatenation,
  • apply allow-list validation where necessary,
  • limit database permissions,
  • and test database-connected features regularly.

Ultimately, SQL injection demonstrates a broader cybersecurity principle:

Security depends not only on what data enters a system, but also on how each layer interprets and passes that data to the next one.

When applications clearly separate instructions from user input, one of the most well-known web application vulnerabilities becomes far easier to prevent.

References