(Image source: WordPress )
WordPress the easiest, one of the most powerful blogging and website content management system has silently fixed a dangerous vulnerability in WordPress REST API Endpoint which was recently added to WordPress version 4.7.0 and enabled by default. The REST API has been affected by an unauthenticated privilege escalation vulnerability, that could possibly lead to Remote Code Execution depending on the plugins installed on a site.
The REST API (Representational State Transfer Application Programming Interface) enables WP to easily communicate with other websites and services, as it is JSON based, and allows to exchange content and data with other web properties regardless of the programming language they are written in.
Where does the vulnerability exist?
The “./wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php” script in WordPress 4.7.0 has a function register_rest_route which is designed to set ID parameter with digits. “/wp/v2/posts/” is the endpoint for creating, deleting or updating WP posts. If we want to update any post on WordPress, send a request to the endpoint API with the ID as 111, the endpoint for updating the post will be “/wp-json/wp/v2/posts/111“.
Please refer to the image below for register_rest_route function implementation.
Adding an id to the end of an endpoint alone can avoid adding a malicious id, but the ‘id’ parameter in REST API accepts non-numeric digits which are key to exploit the vulnerability further.
i.e a crafted request like “/wp-json/wp/v2/posts/111?id=111SecPodTest, will assign parameter ‘id’ value with ‘111SecPodTest‘ which has both digits and letters .
Now our alphanumeric id (111SecPodTest) will be sent to function update_item_permissions_check (as seen in the above image) to check whether the post with the corresponding id exists and has proper permissions to edit the post. The only case where you will be stopped from continuing further is when the post with the given crafted id exists and permission to edit the post doesn’t exist. But in our case, the post id assigned does not exist, and we can pass through to continue execution with the update_item method without being stopped because all WordPress posts have numeric id’s.
The update_item method accepts the non-numeric id where it uses PHP’s int casting (as seen in the above image) to convert the accepted id to an integer. Crafted id parameter containing the value ‘111SecPodTest‘ will be converted to ‘111‘, which is an existing valid post id.
An example code demonstration on how PHP’s int casting works.
php > $id = "111SecPodTest";
php > echo (int) $id .PHP_EOL;
Once the id has been converted to an integer and if the post with corresponding converted id is present, then the update will be applied successfully. Attackers can also perform something like /wp-json/wp/v2/posts/111?id=222SecPodTest to change the post whose ID is 222.
How Dangerous is the Vulnerability?
Using this Content Injection vulnerability attackers can run automated attacks with random id’s (1 to n) to edit the posts, which can add advertisements to posts, or modify the contents of the post.
Depending on the plugins installed on the site even PHP code could be executed very easily.
Just an automated attack of this vulnerability can compromise thousands of posts at a single shot. The impact of successfully exploiting this vulnerability could lead to content injection, code execution and is considered critical as most of the world’s top websites runs WordPress.
WordPress Versions 4.7.0 and 4.7.1
What to do?
WordPress has successfully patched the vulnerability in its latest release. The auto-update system in WordPress automatically updates sites to version 4.7.2. If you haven’t enabled the auto update feature, then please do it asap.
WordPress security advisory states:
We believe transparency is in the public’s best interest. It is our stance that security issues should always be disclosed. In this case, we intentionally delayed disclosing this issue by one week to ensure the safety of millions of additional WordPress sites.
WordPress 4.7.2 released to the world. The release went out over our auto update system and, over a couple of hours, millions of WordPress 4.7.x users were protected without knowing about the issue or taking any action at all.
Security Research Engineer