wp2shell: more than a month later. Confirm 6.8.6, 6.9.5, 7.0.2. Patched is not clean.

Read the advisory

SQL injection attacks on WordPress: how they work and how to reduce risk

What SQL injection is, how it shows up on WordPress sites, and the defenses that matter: prepared statements, trusted plugins, and least privilege.

Topics Malware & cleanup Beginner guides

Lars Koudal

Lars Koudal

Updated Published

SQL injection is still a serious WordPress risk, mostly through vulnerable plugins and custom code that build database queries from user input. Core WordPress APIs are careful when used correctly. Third-party code is where SQLi usually appears.

Dictionary: SQL injection.

What SQL injection is

An attacker sends crafted input (form fields, query strings, headers, REST bodies) that changes the meaning of a database query. If the application concatenates that input into SQL, the attacker can read, change, or delete data, and sometimes escalate further.

Classic sketch (do not use this pattern in real code):

SELECT * FROM wp_users WHERE user_login = '$user_input' AND user_pass = '$password_input';

If $user_input is something like admin'--, the password check can be commented out, depending on how the rest of the query is built. Real exploits are messier. The idea is the same: user input stops being data and becomes part of the command.

Common SQLi styles

  • Error-based: force database errors that leak schema details
  • Boolean-based blind: true/false responses map out data bit by bit
  • Time-based blind: delays (SLEEP) confirm guesses when no data is returned
  • UNION-based: stitch extra SELECT results onto a legitimate query

WordPress sites usually get hit through a vulnerable plugin endpoint, not through the comment box on a fully updated core install.

Impact on WordPress

Successful SQLi can expose user emails and password hashes, alter options (including site URLs), create admin users, or plant content for spam SEO. Breach costs and reputation damage follow if customer data was involved. Prevention and fast detection matter more than clever table names.

Defenses that actually help

Use the WordPress database APIs correctly

In custom code, never concatenate $_GET / $_POST into SQL. Use $wpdb->prepare() (or the higher-level APIs that do parameterization for you):

$login = isset( $_POST['log'] ) ? sanitize_user( wp_unslash( $_POST['log'] ) ) : '';
$row   = $wpdb->get_row(
	$wpdb->prepare(
		"SELECT ID FROM {$wpdb->users} WHERE user_login = %s",
		$login
	)
);

Developers: escape late, validate early, and prefer APIs like WP_Query when they fit.

Keep plugins few and updated

Most WordPress SQLi advisories are plugin bugs. Install less. Update faster. Prefer maintained vendors. Related: plugin security risks, vulnerabilities hub.

Least privilege for the database user

The MySQL user in wp-config.php should not be a server-wide root account. Limit it to the site database. That does not stop SQLi inside that database, but it reduces blast radius on shared servers.

Table prefix changes are not a SQLi fix

Changing wp_ to a custom prefix is fine on new installs for mild obscurity. It does not stop injection. Attackers discover real table names easily once a query is injectable. Do not rebuild a live site just to rename prefixes and call it hardening.

Encryption and backups

Encrypt sensitive application data where it makes sense, and keep restore-tested backups. Encryption does not block SQLi. It can limit how useful stolen rows are. Backups limit how painful destructive queries are.

Monitor and respond

Watch for odd admin users, sudden option changes, and malware after a plugin CVE. Malware scanner, events logging, signs your WordPress site is hacked, and the hacked site guide if you are already in incident mode.

Bottom line

SQLi on WordPress is usually “vulnerable plugin + unpatched site,” not a mysterious core failure. Patch, shrink the plugin list, write parameterized SQL in custom code, and keep backups. That is the practical stack.

Found this useful? Share it.

Larger screenshot