Detailed Static/Dynamic Analysis For (CVE-2022-21661)
Introduction:
Most likely in such cases where we have a CVE ID number and we want to investigate more about it either to write a working POC or any other purposes one of our approaches is to start from the action that the vendor’s dev team has taken in order to patch the vulnerability.
For this case ( CVE-2022–21661 - SQL injection in the Core of Wordpress ) the Wordpress developers team action to patch this issue can be seen in the following commit:
Investigation:
As we have seen above, it’s clearly that the issue is about the $query['terms']
in line 559
which’s located in wp-includes/class-wp-tax-query.php
so we installed Wordpress locally and fired-up the VS Code to start investigating more and figure out what’s wrong with $query['terms']
The array $query
is being passed as a parameter to the function clean_query
which is to Validates a single query
Th function clean_query()
has two conditions , so let’s see how we can avoid changing the value of $query['terms']
.
One thing could be done is making the $query['taxonomy']
empty and assigned term_taxonomy_id
to $query['field']
then we will hit the line 559
without any changing of the $query['terms']
value we will continue till the line 579
$this->transform_query( $query, 'term_taxonomy_id' );
let’s see what’s that function transform_query() doing :
it firstly check if the $query['terms']
is empty or not ( which’s not empty in our case) then it will make sure that $query['field'] == $resulting_field
at line 601
which’s already satisfied since it’s passed 'term_taxonomy_id'
as the second parameter in the previews step
$this->transform_query( $query, 'term_taxonomy_id' );
Now since we Successfully reached to this point it means two things:
1-What ever we put in $query['terms']
won’t be changed ( we made sure of that in above steps)
2-We just need to find a way to make this useful for us.
Exploitation:
Looking at the CVE-2022–21661 description in MITRE we can see that it can be reached from WP_Query class
By simple search we figured out that the WP_Query class is located at wp-includes/class-wp-query.php
So we start by reading the public function __construct()
From there we see that our query will be passed to query()
which will Sets up the WordPress query by parsing query string.
Then it will return return $this->get_posts();
so we jumped to the get_posts()
which Retrieves an array of posts based on query variables
and at line 2138
it will take us to $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' );
By doing so the path to trigger the Error-Based SQL injection was:
__construct()> query()> get_posts()> get_sql() at line 2138> get_sql_clauses() at line 250> get_sql_for_query() at line 247> get_sql_for_clause() at line 324> clean_query() at line 394
Finally, after lots of breaking-points and tracking down the whole issue our team has made this plugin that will firstly create an object from the WP_Query class
then passing all the requirements we discussed above and finally making a Non-authenticated Ajax actions for logged-out users.
<?php
/*
Plugin Name: CVE-2022-21661 Plugin
Description: This plugin was made in order to test ( CVE-2022-21661 )
Version: 1337
Author: Confidential Team
Author's Twitter : @ConfidentialTM
*/
function testinSQLinjection(){
//Args to be passed to the WP_Query class object
$args = array(
'tax_query' => array(
'Confidential' => array(
'field' => 'term_taxonomy_id',
'terms' => array("'"),
)
)
);
//WP_Query class object with specific args 2 trigger the SQLinjection
$trigger = new WP_Query($args);
return $trigger;
}
// Non-authenticated Ajax actions for logged-out users
add_action('wp_ajax_nopriv_Confidential','testinSQLinjection');
?>
Activating the plugin:
Then in order to track all the steps and making sure of everything we sat-up breaking points and send the request:
Here we can noticed from the Variables section at the top-left corner that the $query['taxonomy']
is empty and $query['field'] = term_taxonomy_id
Finally:
Conclusion:
This vulnerability arises at the core of Wordpress yet it couln’t be triggered without a plugin or theme that goes the whole way we discussed above.
Credit :
This issue was documented back 2019 by @Paul_Axe and at the end of 2021 year the GiaoHangTietKiem JSC team has reported it to the Wordpress team and got the CVE for it several days ago jan 6, 2022.
References:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21661
- https://github.com/WordPress/WordPress/commit/271b1f60cd3e46548bd8aeb198eb8a923b9b3827?diff=split
- https://2019.zeronights.ru/wp-content/themes/zeronights-2019/public/materials/7_PaulAxe_ZN_PWN_Challenge.pdf
- https://cognn-medium-com.translate.goog/sql-injection-in-wordpress-core-zdi-can-15541-a451c492897?source=social.tw&_x_tr_sl=vi&_x_tr_tl=en&_x_tr_hl=ar
- https://wordpress-org.translate.goog/news/2022/01/wordpress-5-8-3-security-release/?_x_tr_sl=vi&_x_tr_tl=en&_x_tr_hl=ar