There’s lots of ways to fix SQL injection in WordPress. In this article we cover the best ways to prevent SQL injection and procedures for recovery if a SQL injection attack occurs.

How Does SQL Injection Work?

Hackers target WordPress a lot because it’s popular. And one of the ways they hack WordPress sites is through SQL injection. If that’s not a familiar term, this is how SQL injection works. WordPress uses two components to carry out its operations. The website’s code is written in PHP, and the PHP code connects to a SQL database that stores the site’s data. PHP retrieves data from the SQL database and then formats it and presents it to the website’s users. With e.g. posts, a post is stored in separate parts in the database: author, date, content, title, etc., then the parts are combined using a template and the result of processing the template is that post’s HTML page.

To retrieve the data for a post, PHP runs a SQL query: this is a statement that is similar to English that retrieves specific data from the database. It looks like this: SELECT ID, post_author, post_date, post_content, post_title FROM wp_posts WHERE ID=1;. This example retrieves various data concerning the post with post ID 1. If you recall what WordPress URLs look like before you turn on permalinks, they have have a parameter ?p=NUMBER – e.g. ?p=1. This number is the post ID. Since this post ID gets copied into the SQL query, consider what happens when the post ID isn’t 1, but something else: perhaps “1 OR ID=2“.

This is sneaky: instead of providing a numerical post ID, we’re providing a fragment of SQL. If that SQL is copied directly into the SQL query that PHP runs against the database, interesting and dangerous results are obtained! In this case, the database will retrieve two sets of data instead of one, and that’s probably not the intent of the PHP code performing the query. But worse things are possible. Often the entire database can be retrieved by meddling with fragments of SQL like that, that are injected into a query being run. And since there’s nearly always sensitive data in the database, like password hashes and customer information, this is a problem.

WordPress’s SQL Injection Prevention

Thankfully WordPress provides safeguards against this. WordPress itself uses query parameters, which reduce the likelihood of copying dangerous fragments of SQL provided by anyone into the SQL queries that are actually run. This is a mechanism that checks each piece of data going into a SQL query and makes sure it’s only a number, for instance, instead of a bunch of SQL. This mechanism works well for WordPress itself (the core code) and any plugins and themes that choose to use it.

More problematic is plugins and themes that don’t use this mechanism. Since they have enough freedom to run whatever SQL queries they like, they can create security problems.

The Best Fixes for WordPress SQL Injection

1. Use a Security Plugin that Filters SQL Queries at the Database Level

WordPress core does a pretty good job of preventing SQL injection, mostly. But no code is bug-free, and sometimes there’s a bug in WordPress core code that means SQL injection is possible. And since plugins can introduce SQL injection bugs of their own, and most WordPress sites need to use plugins, the best approach is to look for SQL injection and prevent it at the time it’s happening. Because there’s a single place where all SQL injection happens – the connector or “adapter” between PHP and the database – this is an ideal chokepoint to block any SQL injection happening.

This approach has the two main benefits. Because all SQL queries go through the SQL adapter, it doesn’t matter if the bug allowing the SQL injection is in a plugin or in WordPress core or somewhere else; it will be blocked all the same. Additionally, it doesn’t require disabling plugins your site might depend on if they’re found to have a SQL injection vulnerability, because the vulnerability is handled in another place.

2. Use a Web Application Firewall

Web Application Firewalls filter requests that are sent to a web application, like a WordPress site. Since a SQL injection attack needs to get the injected SQL from somewhere, a WAF that sits between the WordPress site and all users of the site is another good place to block SQL injection attacks. Some security plugins include a WAF as part of their functionality, but you could also use a 3rd-party service that provides a WAF for any type of website and not just WordPress.

This has most of the same advantages as point 1, with one slight drawback in comparison: because the WAF cannot inspect the entirety of each SQL query being run, it’s slightly harder to detect SQL injection, as each source of input to the SQL query must be examined separately and only separately.

3. Use a Web Host or Security Plugin that Scans for Vulnerable Plugins and Themes

Since WordPress core is usually safe, the most value in prevention comes from looking at plugins and themes for code that’s vulnerable to SQL injection. When people discover bugs in plugin code and report the vulnerability so hackers don’t exploit it, some web hosts and security plugins take this information and notify website owners about the problem. This allows website owners to disable or update the vulnerable plugin. This process works, and while sometimes it’s possible to disable a vulnerable plugin or theme automatically, doing so has functionality implications for the website: some functionality might break and be unavailable until the website owner intervenes with updated plugin code or an alternative plugin. Hence, this option is less attractive than options 1 or 2.

4. Only Use Code from Trusted Vendors

The code running on your WordPress site matters quite a lot. Even if you have the ability to read plugin code and find vulnerabilities or look for secure programming, there often isn’t time available, and doing so somewhat defeats the point of using code you haven’t written yourself.

It’s possible to help mitigate the risks from 3rd-party code by following some guidelines:

  1. Larger vendors often, but not always, provide more secure code than smaller vendors, because more review of the code happens.
  2. Companies have more to lose by shipping insecure code than individuals providing free plugins, so the companies are not as likely to ship insecure code.
  3. Compare the record of various vendors. If their products have lots of reported vulnerabilities, or the company has experienced lots of data breaches, they might not take security seriously and you should consider not using their products.

What If SQL Injection Already Happened? How do I fix my website?

Contact Your Host’s Security Team

If you’ve received notification SQL injection occurred, whoever detected the SQL injection can probably tell you what the impact was. Your web host’s security team is likely the best contact, but if you’re not using managed hosting and there’s no security team available, there’s a lot you can do yourself too.

Identify Affected Plugins Using Website Logs

Usually it’s possible to identify HTTP requests that use SQL injection by looking at your website’s logs: the things to look for are odd-looking requests that are longer than normal and include funny characters and seeming gibberish. Where a normal request might look like this:

IP.AD.DR.ES - - [13/Oct/2020 10:10:10 +0000] "GET /checkout/ HTTP/1.1" 200 "http://example.com/cart/" "WebKit 1.0 Browser Info"

… a SQL injection request will often contain a lot of extraneous nonsense between the word GET and the word HTTP, particularly keywords followed by parentheses (CONCAT(), CHR(), SUBSTR()) as well as other SQL keywords (OR, AND, JOIN, UNION SELECT). Locating a SQL injection request in the logs can tell you the location of the affected PHP code on your site: often this will be /wp-content/plugins/<plugindirectory>/<file>, and then you know what plugin is vulnerable and needs disabling or upgrading. (This isn’t a foolproof method, though: SQL injection can use different types of requests that don’t appear in the logs.)

Perform Malware Cleanup and Site Recovery

There might be visible signs of website compromise: malware, your site is broken, your site redirects to another website you don’t control, your admin password has changed. In those cases, the same malware-recovery procedures as normal are used: change passwords, restore your database and website files from a backup, upgrade your security.

An Ounce of Prevention

It’s a good idea to plan ahead when building a WordPress site and consider SQL injection attacks in your security plan. They are much better prevented than recovered from. Once somebody gains access to your data who shouldn’t have access, it’s not possible to remove their access, so build a secure website from the beginning.

Similar Posts

Leave a Reply