04 Feb

The WordPress REST API Opening Up New Front for Security Vulnerabilities in WordPress Plugins

When it comes to the causes of security vulnerabilities in WordPress plugins we haven’t seen something truly new for some time, so that makes something we recently started seeing a pickup of, notable. That being vulnerabilities that are exploitable through WordPress’ REST API. The vulnerabilities are not caused by the REST API, but increasing usage of it in plugins is making more code accessible through it that isn’t properly secured. The API was introduced in WordPress 4.4, which was released back in December, 2015, so this comes with a bit of delay (maybe because developers were waiting till there was wide adoption of WordPress versions that supported it).

Right now we are continuing to evaluate how to respond to this in terms of things like our Plugin Security Checker and in the security reviews we do of plugins. For the latter, we are going to starting doing some checking over this type of code during upcoming reviews to get a better idea of what is going on, before considering official adding any checks related to it our reviews.

A vulnerability we happened to run across seems to show a good example of how usage of the REST API can exacerbates security problems.

While starting to check over code in the plugin Accessibility Suite by Online ADA due something it being flagged by our proactive monitoring of changes made to WordPress plugins in the Plugin Directory to try to catch serious vulnerabilities we happened across this line of code with a SQL statement that wasn’t properly secured with a prepared statement:

$results = $wpdb->get_results("SELECT * FROM $table_name WHERE SCANID = $scan_id");

There are two variables in that, which if they included user input, could lead to a SQL injection vulnerability.

The first, $table_name, doesn’t include user input, so it isn’t an issue:

$table_name = $wpdb->prefix . "oada_scans";

The other variable comes from a value passed to the function that code is in:

static function get_scan_data($scan_id)

That function is called in three locations and all of them pass user input as the value.

One of those is in the function guideline_csv() in the file /includes/rest_routes/csv-routes.php:

function guideline_csv($request)
    $scan_data = Helper::get_scan_data($_GET["scan_id"]);

That function in turn is register to run through the REST API:

add_action( 'rest_api_init', __NAMESPACE__ .'\\csv_guideline_download' );
function csv_guideline_download() {
   register_rest_route( 'ada-plugin/v1', "/guidelinecsv", array(
       'methods'  => 'GET',
       'callback' => __NAMESPACE__.'\\guideline_csv'
   ) );

That registration allows anyone to access guideline_csv() and pass user input that leads to SQL injection by making a request to /wp-json/ada-plugin/v1/pagecsv.

Seeing as the legitimate usage of that functionality is accessed through the plugin’s Scan Results page in the admin area of WordPress, it doesn’t seem like it would be intended to be accessed by those not logged in. The SQL injection vulnerability is exploitable directory through Scan Results page as well, but access to that is limited to users logged in with the Editor and Administrator roles. So the insecure usage of the REST API made the situation worse, though the SQL injection vulnerability should have been avoided even if it existed by properly securing the SQL statement (which is something that we already check for in our security reviews).

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since a previously full disclosed vulnerability was quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Proof of Concept

With the following proof of concept it will take varying amounts of time for the page to load depending on how long you specify MySQL sleep function to run.

Make sure to replace “[path to WordPress]” with the location of WordPress, “[scan id]” with the ID of scan report, and “[sleep time]” with how many seconds you want sleep to occur for.

http://[path to WordPress]/wp-json/ada-plugin/v1/pagecsv?scan_id=[scan id] AND SLEEP([sleep time])

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service you can suggest/vote for the plugins you use to receive a security review from us. You can start using the service for free when you sign up now.

Leave a Reply

Your email address will not be published. Required fields are marked *