Skip to content
>_ITDITDWeb Security Platform

Glossary

What is SQL injection (SQLi): a flaw that lets input rewrite your database commands

SQL injection (SQLi) is when user input rewrites the meaning of a database query (SQL), leading to reading, altering, or wiping data. How it works, and the main defense (placeholders / prepared statements, ORMs, least-privilege DB users) — explained defensively, without attack steps.

Published 2026-06-08 Updated 2026-10-06 9 min read

SQL injection is when text you type into a search box becomes "part of a command" to the database. Here's how it works and how to reliably prevent it (no attack steps).

Why it happens (the mechanism)

The root cause is building SQL by string concatenation. Mix input straight into the statement and it can cross the "value boundary" and act as command.

✗ String concatenation (dangerous)

Input concatenated into the statement → input can be read as part of the command

✓ Placeholders (safe)

Values passed into ? / $1 slots as data → always stay values

Concatenate input and it crosses the value boundary, changing the command. With placeholders, a value stays a value.

The damage is "everything that DB connection can do." If the internal DB is reachable, it's a classic cause of mass leaks, alongside RCE and SSRF.

Defense

1

Use placeholders / prepared statements (most important)

Don't build SQL by concatenation. Pass values via ? / named parameters as 'data'. This alone nearly eliminates the whole class.

2

Lean on your ORM / query builder

Most ORMs use placeholders by default. The less raw SQL you hand-write, the safer. If you must write raw SQL, always parameterize it.

3

Least-privilege DB user

Don't grant the app's DB user unneeded rights (DROP, other tables, admin ops). Even if breached, contain the damage.

4

Input validation as a supplement

Type/length/format checks help, but don't make them your primary defense; they add to placeholders.

This site's view: stop hand-building raw SQL in the first place

SQLi has been known for a long time yet still happens, because it's "convenient" to mix input into the statement. This site's stance is plain: never create a place where values are string-concatenated into SQL. Make placeholders or an ORM the default and this vulnerability is prevented by design. Don't rely on manual escaping.

Watch out: placeholders only carry values

Placeholders don't cover everything. They carry values only — not query structure like table names, column names, or the ORDER BY direction (asc/desc).

When you need those dynamic (e.g. letting a user pick a "sort key" or "filter column"), don't drop input into SQL — select the real name from a predefined allowlist instead. "Sort column" and "filter column" are the classic blind spots where people assume placeholders have them covered.

Input is not just form fields

If you think only search boxes and login forms need care, you will miss cases. Values that can end up in SQL arrive by many routes.

  • HTTP headers (User-Agent, X-Forwarded-For and so on) and cookies
  • Values in JSON received by an API, or read from files
  • Values saved to the database once and later built into SQL by another process

The last one is called second-order SQL injection. Even if you used placeholders when saving, it works when another process string-concatenates the stored value later. Don't assume "it came from my own database, so it's safe": use placeholders wherever SQL is built.

This site's explainer on X-Forwarded-For spoofing describes a case where probe strings arrived in a header, but SQL injection did not work because the value was passed with a placeholder.

How it differs from similar terms

Flaws with "injection" in their name share one thing: input is read as commands in another language. The difference is where the input ends up.

TermWhere the input ends upMain damageRoot fix
SQL injectionCommands to the database (SQL)Reading, altering or deleting dataPlaceholders
XSSHTML or JavaScript running in the user's browserAbuse of the user's session, fake content on the pageEscaping on output and CSP
OS command injectionCommands run by the server's shellRunning any command on the server (RCE)Use APIs that skip the shell and pass arguments separately

SQL injection and XSS are often mentioned together, but the damage lands in different places: SQL injection hits the database on the server, XSS hits the user's browser.

What placeholders are called in major languages

Every major language provides a way to pass values separately. Use this as a guide to which feature to use in your stack.

Language / libraryFeature to use
Java (JDBC)PreparedStatement with value setters such as setString
PHP (PDO)Prepare the statement with prepare, pass values to execute
Python (DB-API)Pass values as the second argument to execute (don't embed them in the SQL string)
Node.js (pg and others)Numbered symbols like $1, with the values passed as a separate array
C# (.NET)Add values to the command's Parameters

In any language, the moment you embed values into the SQL with template strings or +, this protection stops working.

Real examples: large leaks that started with SQL injection in a product

SQL injection has been known for a long time, yet it still causes major leaks. Recent cases often started not in code people wrote themselves, but in a product they used.

CaseWhat happened
MOVEit Transfer (2023)SQL injection in a file transfer product (CVE-2023-34362) was exploited before a fix existed, and data from more than 2,700 organizations was taken, many of them through vendors (→ the MOVEit mass data breach)
Metabase (2026)Unauthenticated SQL injection in an analytics tool (CVE-2026-72898) was exploited before the fix, and several companies disclosed customer data leaks (→ Metabase exploitation and leaks)
WordPress core (2026)Combined with another flaw, unauthenticated SQL injection could lead to RCE (→ CVE-2026-63030 explained)

After MOVEit, the US agencies CISA and FBI issued an alert in March 2024 urging software makers to eliminate SQL injection, naming parameterized queries (placeholders) as the fix. In MITRE's "CWE Top 25" published in December 2025, SQL injection (CWE-89) ranks second.

What to do depends on your role

Your roleFirst thing to do
You write SQL (developer)Stop concatenating strings; use placeholders or an ORM. Review how raw-SQL functions are used
You run products or open source (operator)Check the CVEs and KEV status of the products you run and update to fixed versions. Reduce admin screens reachable from the internet
BothGive the app's database user least privilege, limited to the tables and columns it needs

How to check your own environment

You do not need to type attack strings to test this. Code and settings tell you what you need.

1

Find SQL built from strings

Search your code for lines where SQL keywords (SELECT, WHERE and so on) appear together with string concatenation or template strings. Also check that no input is concatenated into raw-SQL functions ($queryRawUnsafe, whereRaw, DB::raw, raw() and similar).

2

Write down what the database user can do

Check which tables the app's database user can access and what it can do there (SHOW GRANTS on MySQL, information_schema.role_table_grants on PostgreSQL). Remove delete rights it does not need and any access to other apps' tables.

3

Match the products you use against vulnerability data

Use the CVE / KEV Lookup to see known vulnerabilities in the products you run and whether they are being exploited. For dependencies, osv-scanner checks them all at once.

4

Make sure SQL errors are not shown on screen

In production, confirm that database error messages are not shown to users as-is. Keep detailed errors in logs only.

5

Look for signs in your logs

Check whether database syntax errors have suddenly increased, and whether your WAF or access logs show a run of requests from the same source containing SQL-like strings. If so, review the code behind that route first.

Sources (primary)

  • OWASP, "SQL Injection Prevention Cheat Sheet" — cheatsheetseries.owasp.org (placeholders, cautions on stored procedures, allowlist input validation, least privilege, not relying on escaping)
  • CISA and FBI, "Secure by Design Alert: Eliminating SQL Injection Vulnerabilities in Software" (March 25, 2024) — cisa.gov
  • MITRE, "2025 CWE Top 25 Most Dangerous Software Weaknesses" (December 2025) — cwe.mitre.org (CWE-89 ranked second)
  • IPA, "How to Secure Your Web Site" — ipa.go.jp (Japanese; fundamental solutions vs mitigations)

Classification

CWE classifies the types of weakness behind vulnerabilities; MITRE ATT&CK classifies attacker techniques. Both are maintained by MITRE and widely used to label vulnerability reports and detection rules.

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

© 2026 The MITRE Corporation. This work is reproduced and distributed with the permission of The MITRE Corporation. MITRE ATT&CK and ATT&CK are registered trademarks of The MITRE Corporation. The MITRE Corporation (MITRE) hereby grants you a non-exclusive, royalty-free license to use ATT&CK® for research, development, and commercial purposes. Any copy you make for such purposes is authorized provided that you reproduce MITRE's copyright designation and this license in any such copy. ATT&CK Terms of Use

FAQ

QWhat happens with SQL injection?
A

An attacker changes the meaning of a database query — reading data that should be hidden, altering it, or at worst wiping everything or bypassing authentication. It's a classic cause of mass data leaks.

QWhat's the most reliable defense?
A

Pass values via placeholders (prepared statements). Don't build SQL with string concatenation; pass values as 'data' through a separate channel so input can never be read as command. Most ORMs do this by default.

QIs escaping input enough?
A

Manual escaping is error-prone and discouraged. Use placeholders. Also give the DB user least privilege to limit the damage if something gets through.

QIf I use an ORM, am I safe?
A

In normal use, yes: ORMs pass values as placeholders by default. But if you concatenate input into the raw-SQL functions they offer (Prisma's $queryRawUnsafe, Laravel's whereRaw and DB::raw, Django's raw and extra, and so on), the same flaw comes back even with an ORM. Parts that placeholders cannot carry, such as sort column names, also need care.

QCan a WAF stop SQL injection?
A

It helps reduce the damage but is not the root fix. Japan's IPA guide 'How to Secure Your Web Site' also separates the fundamental solution (placeholders) from mitigations that only reduce the damage. A WAF is a mitigation, and some input slips past detection. Use it as a stopgap until the code is fixed.

QHow do I find out whether a product I use has SQL injection?
A

Match the product name and version against published vulnerabilities (CVEs) and CISA's KEV list of vulnerabilities confirmed as exploited. This site's CVE / KEV Lookup can do this. As MOVEit Transfer and Metabase showed, SQL injection in a product you use has led to large data leaks more than once.

QWhat is a prepared statement?
A

A mechanism where the shape of the SQL statement (where the values go) is sent to the database first, and the values are sent separately afterwards. The spots for values are marked with symbols such as ? or $1 (placeholders). Because the shape is fixed first, the values sent later are never read as commands, whatever characters they contain.

QWhat is blind SQL injection?
A

A kind of SQL injection where the database contents and errors are not shown on screen, yet information can still be read bit by bit from differences in responses or response times. Showing nothing on screen does not make a site safe. The cause and the fix are the same as ordinary SQL injection: with placeholders it does not work.

QDoes hiding error messages prevent it?
A

No. Hiding errors makes the flaw harder to find, but as blind SQL injection shows, information can be read even when no error appears. You should not show errors on screen, but separately you still need to fix every place that builds SQL by string concatenation.

QAre stored procedures safe?
A

Written correctly, they are as effective as placeholders. But OWASP warns that if a procedure builds SQL inside itself by concatenating input (dynamic SQL), the same problem comes back. Check what the procedure does inside.