On February 1st, 2017, Sucuri Security disclosed a 0-day vulnerability in WordPress. If you are running WordPress version 4.7.0 which was released on December 6, 2016, or 4.7.1 which was released on January 11th, 2017, you should stop reading and go update immediately!
The disclosure describes the privilege escalation vulnerability which was found in the core of WordPress, affecting the newly updated feature: the REST API. This vulnerability could allow anyone to modify any post or page on a WordPress site without even being authenticated! Pretty scary, right? Good thing this issue was found by security researchers!
They responsibly disclosed the flaw to WordPress Security on January 20th and they fixed it right away, making a silent patch on version 4.7.2, which was released on January 26th, 2017, and protecting anyone who performs automatic updates on their sites. The WordPress Security Team has also reached out to several companies with WAF products including SiteLock, Cloudflare, and Incapsula to help them create rules in their tools to protect their customers and make sure no harm would be done until the fix was released. After that, WordPress hosting providers were alerted about this issue, how the vulnerability worked and how to protect their customers’ sites.
This vulnerability affects the WordPress Rest API. According to the security researcher who discovered the vulnerability, one of these REST endpoints (WP_REST_Posts_Controller) allows anyone to access to view, edit, delete and create posts via the API. The REST API was added and enabled by default on version 4.7.0, leaving versions 4.7.0 and 4.7.1 vulnerable to this flaw!
The flaw in the WordPress REST API works due to a “feature” in PHP, also present in some other languages, called type juggling. It allows the developer to silently change the values of one type to another. Since PHP doesn’t require explicit type definition in a variable declaration, that feature is permitted. What does that mean? It means that when comparing a string to a number, PHP will attempt to convert the string to a number then perform a numeric comparison. If you are comparing a string like “123CODEGUARD” to an integer variable, only the numbers will be used for the comparison operation. Watch the examples below:
The problem is that PHP has two comparison modes: loose and strict. Loose comparisons have a set of operand conversion rules to make it easier for programmers, unfortunately even PHP developers admit that “[it] may not be obvious exactly what will happen when casting between certain types.” Although PHP type-juggling bugs are very common, they are difficult to exploit because you are usually not able to input typed data over HTTP. Unfortunately, that was not the case with the WordPress REST API.
WordPress REST API Code
Let’s go back to the WordPress code now. More specifically the code inside /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php file, where they found the input validation issue in the update_item function. In this function, the input validation issue that could allow a privilege escalation by a malicious user is the first line of code where they are type-casting the ID from the request to the $id variable. According to this, it would be possible to submit a request to the REST API like /wp-json/wp/v2/posts/123?id=999STRING, which would result in the id variable being set to 999.
The WordPress Team fixed this in version 4.7.2 by ensuring that the id input is not coerced and is validated prior to proceeding:
PoC in the wild
As you can imagine since the disclosure of this flaw there are already exploits in the wild being used to target this problem. A video was made and uploaded to Youtube explaining how it the vulnerability works and how to exploit it. You can watch it here:
Some security researchers also published a few Proof of Concept (PoC) tests to check if your site is vulnerable. Here is one from Larry Cashdollar, who works at Akamai:
Another PoC from Leon Jacobs can be found at his GitHub: https://gist.github.com/leonjza/2244eb15510a0687ed93160c623762ab
Stay up to date
This is a serious vulnerability that can be misused to compromise a vulnerable site. Make sure your WordPress installation is up to date and be safe!