---
title: "SQL injection"
description: "SQL injection explained: how poorly handled input hijacks a query, what a WordPress site risks and why $wpdb->prepare() is the right defense."
language: "en"
locale: "en-US"
type: "definition"
canonical: "https://www.wp-masquerade.com/glossary/sql-injection/"
published: "2026-10-28T08:00:00+00:00"
modified: "2026-10-28T20:06:46+00:00"
translations:
  en-US: "https://www.wp-masquerade.com/glossary/sql-injection/index.md"
  fr-FR: "https://www.wp-masquerade.com/fr/definitions/injection-sql/index.md"
  es-ES: "https://www.wp-masquerade.com/es/glosario/inyeccion-sql/index.md"
  de-DE: "https://www.wp-masquerade.com/de/glossar/sql-injection/index.md"
  it-IT: "https://www.wp-masquerade.com/it/glossario/sql-injection/index.md"
  pt-BR: "https://www.wp-masquerade.com/pt/glossario/injecao-de-sql/index.md"
  nl-NL: "https://www.wp-masquerade.com/nl/woordenlijst/sql-injectie/index.md"
---

# SQL injection

SQL injection is an attack that slips fragments of SQL code into data sent to a website in order to hijack the query the site sends to its database. It can be used to read, modify or delete data, and sometimes to bypass authentication.

Almost every dynamic site, WordPress included, stores its content in a database queried with SQL. When code builds a query by pasting in a value received from the visitor, it mixes two things that should stay separate: instructions and data. The attacker takes advantage of this to write instructions where data was expected. MITRE classifies this weakness as CWE-89.

## How SQL injection works

Take code that looks up a post by name by assembling the query by hand:

```
$sql = "SELECT * FROM articles WHERE name = '" . $_GET['name'] . "'";
```

If the visitor sends `x' OR 'a'='a`, the quote closes the string the developer intended and the rest becomes SQL. The condition is always true: the database returns the whole table. With other payloads, the attacker can extract data from other tables, modify it or delete it.

![Comparison between a concatenated SQL query, where the input x' OR 'a'='a makes the condition always true and returns the whole table, and a query prepared by WordPress, where the input stays a plain value](https://www.wp-masquerade.com/media/2026/10/injection-sql-requete-en.webp)

*A prepared statement keeps SQL code separate from values: the input can no longer change what the query means.*

## What an attacker can get

OWASP sums up the possible consequences of a successful injection:

- reading sensitive data: email addresses, orders, password hashes;
- inserting, modifying or deleting records, for example giving an account the administrator role, which makes it a path to [privilege escalation](https://www.wp-masquerade.com/glossary/privilege-escalation/);
- bypassing authentication;
- in some cases, reading files on the server or sending commands to the operating system, all the way to [remote code execution](https://www.wp-masquerade.com/glossary/remote-code-execution/).

Not every injection displays its result on screen. In so-called “blind” variants, the attacker infers the data piece by piece from differences in responses or timing. It is slower, but just as effective with an automated tool. The [vulnerabilities found in WooCommerce since 2020](https://www.wp-masquerade.com/woocommerce-security-vulnerabilities/) include several SQL injections, and the [All-in-One WP Migration alert](https://www.wp-masquerade.com/all-in-one-wp-migration-cve-2026-19949-probed/) shows that such a flaw gets probed as soon as it is disclosed.

*Video: “Hacking Websites with SQL Injection - Computerphile” (Computerphile)*

## For WordPress: $wpdb->prepare()

High-level functions (`WP_Query`, `get_posts()`, `update_option()`…) build their queries themselves. As soon as a plugin writes its own query with the `$wpdb` object, every variable value must go through `$wpdb->prepare()`. Its placeholders are `%s` (string), `%d` (integer), `%f` (float) and, since WordPress 6.2, `%i` for a table or column name.

```
$ids = $wpdb->get_col( $wpdb->prepare(
    "SELECT ID FROM {$wpdb->posts} WHERE post_author = %d AND post_status = %s",
    $author_id,
    'publish'
) );
```

- Don't put quotes around `%s`: the function adds them.
- For a search with `LIKE`, pass the full string as an argument, after running it through `$wpdb->esc_like()`.
- Casting IDs with `absint()` before use is an extra safeguard, not a substitute for a prepared statement.

## How to protect your site as an owner

- Apply plugin security updates quickly: you won't be fixing their code yourself.
- Give the database user only the privileges WordPress needs, to limit the damage of a hijacked query.
- Put a [web application firewall](https://www.wp-masquerade.com/glossary/waf/) in front of the site: its rules spot the best-known injection payloads and can cover a flaw until it is patched.

WP Masquerade neither detects nor blocks SQL injection: it is not a web application firewall. Hiding WordPress makes it harder to identify installed plugins, which gets in the way of some bots, but it never replaces updating the vulnerable plugin.

## Common mistakes

- Escaping “by hand” with `addslashes()` or character replacements instead of using a prepared statement.
- Preparing the values but inserting a column name or sort order taken from the request as is: use `%i` or an allowlist.
- Believing that data safely stored in the database is safe everywhere: on output, it is [cross-site scripting](https://www.wp-masquerade.com/glossary/xss/) you need to prevent, with escaping.

## Related terms

- [XSS (cross-site scripting)](https://www.wp-masquerade.com/glossary/xss/)
- [WAF (web application firewall)](https://www.wp-masquerade.com/glossary/waf/)
- [Remote code execution (RCE)](https://www.wp-masquerade.com/glossary/remote-code-execution/)
- [Privilege escalation](https://www.wp-masquerade.com/glossary/privilege-escalation/)
- [CSRF (cross-site request forgery)](https://www.wp-masquerade.com/glossary/csrf/)


## Sources

- [OWASP : SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
- [MITRE CWE-89 : Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)](https://cwe.mitre.org/data/definitions/89.html)
- [WordPress Developer Resources : wpdb::prepare()](https://developer.wordpress.org/reference/classes/wpdb/prepare/)
