Requirements:
- WP-Statistics Plugin Version <= 12.0.7
- Least Permission account : Subscriber account (with post edit permission)
Why it is easy to exploit?
This vulnerability is caused by the lack of sanitization in user provided data. An attacker with at least a subscriber account could leak sensitive data and under the right circumstances/configurations compromise your WordPress installation.
How it actually Works?
WordPress provides an API that enables developers to create content that users can inject to certain pages just using a simple shortcode:
Shortcode: [shortcode atts_1=”test” atts_2=”test”]
Among other functionalities, WP Statistics allows admin users to get detailed information related with the number of visits by just calling the shortcode below:
As you can see on the above code shortcode.php, some attributes of the shortcode wpstatistics are being passed as parameters for important functions and this shouldn’t be a problem if those parameters were sanitized,but as we’ll see this is not the case.
Example: result = wp_statistics_searchengine( $atts[‘provider’], $atts[‘time’] );
One of the vulnerable functions wp_statistics_searchengine_query() in the file “includes/functions/functions.php” is accessible through WordPress’ AJAX functionality through function wp_ajax_parse_media_shortcode().
This function doesn’t check for additional privileges, allowing subscribers to execute this shortcode and inject malicious data to its attributes.
In a number places in the code, user input coming from attributes of the wpstatistics’ shortcode are included in SQL queries without being sanitized. Below one of the queries that were exploitable:
The wp_statistics_searchengine_query() basically returns the same value as the one passed in the shortcode attribute provider and its content is added directly to the raw SQL query.
Exploit Phase:
When user (subscriber) enter shortcode in post as [wpstatistics stat=”searches” provider=”Google”]
it will call wp_statistics_searchengine() with provider=”Google”, then it call another function wp_statistics_searchengine_query( ), as a result it form a SQL query and stored in variable in $search_query.
Example: $search_query .= “engine
= ‘{$search_engine}’”;
Here search engine = “Google”. which will be as $search_query = “engine
= ‘Google’” It is directly input in most of the SQL queries i.e see below SQL queries statement
$result = $wpdb->query( “SELECT * FROM {$tablename}
WHERE last_counter
= ‘{$WP_Statistics->Current_Date( ‘Y-m-d’ )}’ AND {$search_query}” );
so user input is not sanitized on parameter provider, so which allow user to injection any malicious queries to fetch data from database
Example: This payload will get username, password and email from database and stored into test.txt file.
[wpstatistics stat=”searches” provider=”123’ union select 1,2,user_login,user_pass,user_email,6 from wp_users into outfile ‘/var/www/html/waf-demo/wp-content/uploads/test.txt’#”]