---
{
  "title": "SQL injection",
  "summary": "SQL injection occurs when untrusted input changes the structure of a database command.",
  "topic": "offensive",
  "level": "Intermediate",
  "updated": "2026-10-12",
  "published": "2026-10-04",
  "units": [
    7
  ],
  "aliases": [],
  "sources": [
    {
      "title": "OWASP: SQL Injection Prevention",
      "url": "https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
    }
  ],
  "editorialVersion": 2
}
---

## What it means

SQL injection occurs when untrusted input changes the structure of a database command. It can affect confidentiality, integrity, and sometimes broader system access. The primary boundary is between executable query syntax and data values, which should remain separate throughout query construction.

## A practical example

A search service binds a requested category as a value in a prepared query. For a selected sort order, it chooses from predefined query fragments because identifiers and keywords cannot generally be protected by ordinary value binding.

## What to check

Use parameterized queries through a supported database interface. Review dynamic SQL inside stored procedures, constrain query construction, and give the application account only the database permissions it needs.

## A common pitfall

A stored procedure is not automatically safe if it concatenates input into executable SQL. Escaping strings manually is also more fragile than separating query structure from values.

## Think it through

Can a parameter placeholder safely choose an arbitrary column name?

**Answer:** Usually not. Map a permitted user choice to a trusted identifier or predefined query fragment.

## Trace the value to execution

Imagine a fictional bookshop that accepts a search term and a sort choice. The term is ordinary data, while the sort choice changes how the query is assembled. A review should follow both values from the HTTP request through helper functions to the database call. Seeing a parameter placeholder in one helper is insufficient if a later helper concatenates an additional filter.

The important distinction is what the database is asked to interpret. A reader searching for an author's surname containing an apostrophe should still receive a normal search result. Security should not require banning legitimate names. Separating syntax and values makes the application easier to reason about as well as safer.

Different database interfaces offer different binding behavior. Use the supported driver documentation to confirm that a value is bound rather than formatted into a string before execution. Review raw-query escape hatches in object-relational mapping libraries. The presence of an ORM does not automatically cover every query the application runs.

## Explain the finding without extracting records

In an authorized classroom application, compare two implementations of a product search using harmless test records. Draw the query structure separately from the values supplied to it. Describe how each implementation handles punctuation and an unsupported sort choice. This teaches the boundary without needing production data or destructive commands.

A useful report identifies the affected query path, the permissions of the database account, and the business consequence of altered query behavior. The fix should cover other callers of the same helper and include a regression case. Parameterization prevents a particular interpreter problem; account scoping and least privilege still decide which legitimate queries should be possible.

## Related concepts

- [[injection]]
- [[input-validation]]
- [[database-hardening]]
