Wordpress4.2.3 privilege escalation and SQL Injection Vulnerability (CVE-2015-5623) Analysis
This is a vulnerability that you have been paying attention to over the past few days. wordpress released version 4.2.4 last week, which mentioned fixing possible SQL vulnerabilities and Multiple XSS.
Check point was quickly analyzed. I also analyzed and reproduced the latest vulnerability.
0x01 unauthorized vulnerability caused by GP Mixing
First, describe the background. In wordpress, user permissions are divided into subscriber, contributor, author, edit, and administrator.
The subscriber has the lowest permission. The subscriber has only the permission to subscribe to articles. After wordpress enables registration, the subscriber is the subscriber by default. Many well-known websites in China, such as Freebuf, are registered as "subscribers ".
We first see a permission Escalation Vulnerability. As a subscriber, We can insert an article in the database with excessive permissions.
Wordpress checks whether the user permission is to call the current_user_can function. We can see this function:
Follow up the has_cap method called
Follow up the map_meta_cap function again:
As you can see, this function actually checks permissions. Check the 'edit _ Post' and 'edit _ page' sections for the error code:
It can be seen that when $ post does not exist, the switch logic is directly break, and no code for subsequent checks is executed.
$ Post is the ID of the article to be edited. That is to say, if you want to edit an article that does not exist, return directly without checking the permission.
Under normal circumstances, there is no problem, because there is no article to edit.
Now we can see the part of the background editing article:/wp-admin/post. php
GET $ _ GET ['post'] First, and GET $ _ post ['Post _ id'] only if it cannot be found. That is to say, $ post_ID is from GET at this time.
However, the post_ID passed in when we call the current_user_can function is from POST:
Here is a logic problem. When we pass in the correct postid in the get parameter (this will not produce an error in get_post), and pass in a non-existent postid in The POST parameter, you can bypass the steps to check the edit_post permission.
However, this logic error cannot cause serious harm for the moment, because the code for editing the article is actually in the edit_post function, and the post_ID of this function comes from $ _ POST.
0x02 get _ wpnonce bypass CSRF defense
Wordpress uses _ wpnonce (that is, token) to defend against CSRF vulnerabilities, and its token is very strict. Different operations have different tokens.
For example, to call the edit_post function, the following logic is required:
Check_admin_referer is the function for checking _ wpnonce. When $ post_type = 'postajaxpost', the name of _ wpnonce is "add-postajaxpost ".
How can we get the _ wpnonce name "add-postajaxpost?
See the above position:
There is a post-quickdraft-save operation. This operation is used to temporarily store drafts. As long as the user accesses this operation, a new article with the status of auto-draft will be inserted in the database post table.
The steps are as follows. because we do not know the _ wpnonce name "add-post", we enter the wp_dashboard_quick_press function and follow up:
Fortunately, in this function, wordpress outputs the _ wpnonce in the form.
Therefore, as long as we access post-quickdraft-save, we can get the add-post _ wpnonce, thus bypassing the check_admin_referer function.
0x03 logical vulnerabilities caused by competitive Vulnerabilities
This section is actually the core of this Elevation of Privilege hole. After we get _ wpnonce, we enter the edit_post function.
The purpose is to update an article, but as mentioned in 0x01, if you want to bypass the function of permission check, you need to input an article id that does not exist. So even if we can execute update, we cannot modify an existing article?
This actually involves a logical vulnerability caused by competition. The edit_post function code is displayed:
The above two figures should be very intuitive. After current_user_can mentioned in 0x01 is bypassed, the execution time of the Code is vacuum until the update statement is executed.
For example, the input tax_input = 1, 2, 3, 4... 10000, so the query statement will actually be executed 10000 times, which takes a long time. (Test on my own virtual machine. It takes about 5 to 5 to execute this statement for 10000 times ~ About 10 seconds)
Assume that there is a newly inserted article during this period, then our previous "nonexistent" id, isn't it possible? (You just need to set the id to the latest article id + 1 )?
But the question is, how can we insert a new article during this period? In 0x02, in order to get _ wpnonce, post-quickdraft-save has been executed. Execute post-quickdraft-save to insert an article with the status of auto-draft in the database, but each user can insert only one article at most.
In the original text of check-point, the method mentioned is: wait a week, wordpress will automatically delete this article, and _ wpnonce will be retained for one day, in this way, we can execute post-quickdraft-save again on this day to insert an article.
I thought for myself, but there is no need to worry about it. If we can register another account with the Subscriber Identity, We can insert another article, so my POC does not need to wait for a week.
These three vulnerabilities are combined to create a privilege escalation vulnerability. For the privilege escalation vulnerability described in the first article, I wrote an EXP. After execution, the subscriber can insert an article in the waste bin:
You can see this article on the article editing page:
0x04 SQL injection vulnerability caused by untrash
Therefore, such a Elevation of Privilege Vulnerability does not actually make much sense. Check-point the second article mentions an SQL injection vulnerability caused by this Elevation of Privilege Vulnerability.
Let's talk about the principle of this injection.
/Wp-schemdes/post. php
For example. In many parts of Wordpress, the pre-compilation used to execute SQL statements is limited to those that directly accept user input. It is obviously a secondary operation. First, use the get_post_meta function to retrieve the meta from the database, and then insert the SQL statement by concatenating strings.
This causes a secondary injection.
Let's take a look at how the first warehouse is stored. First, wp_trash_post is the method to delete the article. After deleting the article, wp_trash_post_comments is called to delete the comments under the article:
Follow up with the wp_trash_post_comments function:
For example, we can see that this "comment_approved" is actually obtained from the database. Therefore, this injection is called "three injections ".
Then I will continue to follow up to see where the earliest comment_approved came from.
In fact, we can see the SQL statement in the figure. This comment_approved is a field in the comments table. I have read two functions: add comments and modify comments, this field is involved in the edit_comment function:
Therefore, the final result of this series of operations is an SQL injection vulnerability.
To sum up 1234, the entire utilization process is as follows:
Insert an article with a quick draft-> edit an article without authorization-> insert a comment-> modify a comment (malicious data is imported into the database)-> delete an article (malicious data is imported into another database) -> reverse article deletion (malicious data is taken out and SQL statements are inserted directly to cause injection)
0x05 Study on the hidden part of the original text and the actual use process
I have to mention the original check-point text here. The second full text of the original text does not mention the wordpress token, that is, _ wpnonce. However, almost all operations in the wordpress background require specific _ wpnonce. In the first step, we obtain the "add-postajaxpost" _ wpnonce through a leak point, but in fact every step (add, edit comments, trash articles, untrash articles) different _ wpnonce are required. How can we obtain these _ wpnonce statements?
After my analysis, I could not find the _ wpnonce for "adding comments" and "deleting Articles" with subscriber permissions, the _ wpnonce of "Modify comments" and "delete Articles" can be found in the background.
In addition, although the front-end can also add comments, the front-end will check whether the article is draft, the status is public or private, and we cannot add comments to this article and its derived preview article.
So I upgraded the permissions of the basic account to the permissions of the author who can post and edit the article, and then reproduce the injection vulnerability.
First, post an article and reply to a comment below it:
Let's modify this comment again:
On the article editing page, find trash's _ wpnonce and drop the article to which the comment belongs to the bin:
Find the decompressed _ wpnonce and remove this article from the recycle bin:
Check the SQL Execution records and find that the injection has been successful. single quotation marks are introduced:
Finally, let me summarize this vulnerability.
This vulnerability has two core points: one is an unauthorized vulnerability caused by a logical error in the competition condition, and the other is the last SQL injection vulnerability caused by one or three operations.
These two core technical points are very representative. After learning through the article, I have to admire the idea of dongzhu and the depth of wordpress research.
However, I am also sorry that I failed to analyze how to inject under the minimum permission, mainly because the acquisition of _ wpnonce caused some problems in exploits.
In addition, this SQL injection has a weakness that must be mentioned. When the Contaminated Data is imported into the database for the first time, the field storing the data in the database is only 20 characters long, as a result, our injection point is an injection point with a "length limit". I have not come up with a better method for the utilization of this length limit.
Although the length limit exists, because the injection points appear in the update statement comment table, this vulnerability allows you to set all comments on the entire site to 0, for social websites such as Freebuf, the harm is huge.
Therefore, my evaluation of this SQL injection is: the use of the above (May) is relatively weak, but the idea is absolutely first-class, it is worth learning.