Content Injection Vulnerability In WordPress REST API

Summary

    Recently, a severe content injection vulnerability was discovered in WordPress. This vulnerability allows an unauthorized user to inject malicious content and modify the content of any post or page within a WordPress site.

    TECHNICAL DETAILS

    By conducting a thorough research on the source code of WordPress, we find a vulnerability which allows an unauthorized user to bypass permission check(via REST API) and to modify posts freely. 

    Let’s start with /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php, and have a look at the two callback functions: update_item and its permission check method update_item_permissions_check. 

    blob.png

    

    

    We focus our attention on permission check method update_item_permissions_check. 

    blob.png

    

    The first red box indicates the ID value that is directly passed to get_post() function to check whether the post exists. The second red box is of paramount importance. If the post does exist but our user has no permission to edit this post, this sentence Sorry, you are not allowed to edit this post will be returned. To put it in this way, if we send an ID that does not have a corresponding post, we can just pass through the permission check and come to the last step return true. If the ID provided by our users does not have a corresponding post, our users cannot modify any post even though they have the permission to modify the post. But note that we are now at the permission check stage. 

    

    If our user provides a special ID parameter, which does not have a corresponding post during permission check using update_item_permissions_check function, then the user will gain permission to modify posts. When modifying the post using update_item function, there does exist a post corresponding to the ID, then our user can modify the post. 

    The ID parameter should meet the following two conditions: 

    1.It should not have any corresponding post while executing the function get_post() . 

    2.It should not have any corresponding post while executing the function update_item ().But does this sort of ID really exist? Let’s first have a look at the function get_post(): 

    blob.png

    

    It is obvious that as long as we enter an ID parameter which will make the function get_instance() to output return false, we will get null as a result. That is to say, there is no corresponding post. 

    Then let’s proceed with the function get_instance(), as shown below: 

    blob.png

    

    

    The above codes show that it would basically fail on any input that is not all made of numeric characters, resulting in no corresponding post being found. 

    Now let’s look at another function update_item, which can modify posts. 

    blob.png

    

    Codes in the red box are very important. Here we should ensure that a corresponding post can be found by executing the function get_post(). $id   = (int) $request[’id’]; helps to convert the ID into integers, ensuring that the function get_post() can be successfully executed. So the only requirement is that the ID parameter can be converted into integers, for example, 123abc can be converted to 123. 

    As long as we have this sort of ID parameters, we can bypass permission check and edit posts freely. 

    VULNERABILITY REPRODUCTION

    The following is WordPress4.7.1 which has been installed by default. The first post is Hello World, and the ID of this post is 1. 

    blob.png

    Create a data packet as shown below. ID parameter is 1a. Modify title and content to be Content Injection Vulnerability in WordPress:

    blob.png

    We get the code returned: 200, indicating that the post has been successfully modified. Refresh the page and you will see that the post has been successfully modified. 

    

Solution

    1.The bug is fixed in WordPress 4.7.2. Download link: https://cn.wordpress.org/; 

    2.For Sangfor NGAF customers, update the IPS and WAF to version 20170207 or above.