Disclosure: WordPress WPDB SQL Injection - Technical
Today, a significant SQL-Injection vulnerability was fixed in WordPress 4.8.3. Before reading further, if you haven’t updated yet stop right now and update.
The foundations of this vulnerability was reported via Hacker-One on September 20th, 2017.
This post will detail the technical vulnerability as well as how to mitigate it. There is another post which deals with the background and time-lines.
What Site Owners Should Do
Simply upgrade to 4.8.3 and update any plugins that override $wpdb
(like HyperDB, LudicrousDB , etc). That should be enough to prevent these sorts of issues.
What Hosts Should Do
Upgrade wpdb.php
for clients.
There may be some firewall rules in the mean time that you could implement (such as blocking %s
and other sprintf()
values), but your mileage may vary.
What Plugin Developers Should Do
To prevent this issue? Nothing, it’s been mitigated at the WP layer.
In general however, go through and remove all user input from the $query
side of ->prepare()
. NEVER pass user input to the query side. Meaning, never do this (in any form):
$where = $wpdb->prepare(" WHERE foo = %s", $_GET['data']);
$query = $wpdb->prepare("SELECT * FROM something $where LIMIT %d, %d", 1, 2);
This is known as “double-preparing” and is not a good design.
Also, don’t do this:
$where = "WHERE foo = '" . esc_sql($_GET['data']) . "'";
$query = $wpdb->prepare("SELECT * FROM something $where LIMIT %d, %d", 1, 2);
This is also conceptually unsafe.
Instead, build your queries and arguments separately, and then prepare in one shot:
$where = "WHERE foo = %s";
$args =
Truncated by Planet PHP, read more at the original (another 34330 bytes)