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.