Popular Wordpress analysis plug-in WP-Slimstat weak key and SQL Injection Vulnerability Analysis
The Web security enterprise Sucuri said on Tuesday that they found an SQL injection vulnerability in the latest Wordpress analysis plug-in WP-Slimstat, which allows attackers to perform SQL blind injection, to obtain sensitive information about the database. More than 1 million of Internet sites are affected.
About WP-Slimstat
WP SlimStat is a powerful WordPress real-time statistical analysis plug-in that allows you to view Website access information. The WordPress record shows that the plugin has been downloaded more than 1.3 million times.
Vulnerability Analysis
After analysis, I found that this vulnerability is not a simple SQL injection, but it is quite interesting. Let's take a look at it.
First, when you enable the WP-Slimstat plug-in, whenever you access a web page, the system will send a post request to/wp-admin/admin-ajax.php via ajax, record your current access to the web page.
Shows the data sent:
Data is a base64-encoded piece of data. After decoding, it is
1
ci=YToyOntzOjEyOiJjb250ZW50X3R5cGUiO3M6NDoiaG9tZSI7czo4OiJjYXRlZ29yeSI7czowOiIiO30=.ae93e0c4e2f76695c4dd540456ab7945&ref=&res=aHR0cDovLzEwLjE4LjE4MC4zNy93b3JkcHJlc3Mv&sw=1920&sh=1080&cd=24&aa=1&sl=2004&pp=7267&pl=flash|
We directly go to the plug-in file to see how the plug-in processes the data.
In line 2 of the wp-content \ plugins \ wp-slimstatwp-slimstat.php File
We can see that the data is passed to $ data_string after base64 decoding. Then, it is assigned to $ data_js through the parse_str method.
Next, he did something interesting.
In row 3, we can see that $ data_js [ci] is divided into two parts: ". "$ nonce is assigned to the back end, and the front end overwrites the original $ data_js [ci].
In row 3, he added a secret key to the end of $ data_js [ci]. After md5 encryption, the key is compared with $ nonce. If not, the system will exit the program directly. That is to say, he checks whether the data packet has been tampered with. If the data packet has been tampered with, he will exit the program directly.
Let's continue to look at the data that has not been tampered with, in the 374th rows:
He decoded $ data_js [ci] base64 and then deserialized it and assigned it to $ content_info.
And then in the 417 rows
$ Content_info enters the maybe_insert_row function and follows up with this function. There are 1036 rows.
We can see that the data is brought into the query. In the row 1,044th, we can see that the program uses the database query function provided by wordpress to strictly pre-process the obtained data, however, hundreds of secrets are sparse. The variable $ a_key is not in the pre-processing column, and this variable is controllable. This is also the culprit of this vulnerability.
So the question is: how can we bypass verification and let the program think that the data has not been tampered?
From the above we know that only $ nonce and md5 (self: $ data_js ['cies']. self: $ options ['secret']) the program can be executed only when the program is equal. What we can control now is $ nonce and $ data_js ['cies'], you only need to know $ options ['secret. Let's take a look at what $ options ['secret'] is.
In row 3, we can see that it is a simple value after the current system time is encrypted by md5. The time () function returns a Unix timestamp, which is a 10-bit pure number, in addition, based on speculation about the website establishment time, We can greatly narrow the scope of speculation. According to the test, we can guess the system's secret key about 30 million times. Once we have guessed the secret key, we can tamper with data packets for injection.
I wrote a program and guessed the key in a few seconds.
With the key, we start to inject. Because the injection is on the key value of the array, we add a single quotation mark after the category. The constructed payload is as follows:
1
a:2:{s:12:
"content_type"
;s:4:
"home"
;s:9:
"category'"
;s:0:
""
;}
Encode base64 and add the key md5 to obtain the encryption value of 13688da6b1bad69d677948ebed0fa19a. Add it to the request and encode the request base64 again to obtain our final payload.
Y2k9WVRveU9udHpPakV5T2lKamIyNTBaVzUwWDNSNWNHVWlPM002TkRvaWFHOXRaU0k3Y3pvNU9pSmpZWFJsWjI5eWVTY2lPM002TURvaUlqdDkuMTM2ODhkYTZiMWJhZDY5ZDY3Nzk0OGViZWQwZmExOWEmcmVmPSZyZXM9YUhSMGNEb3ZMekV3TGpFNExqRTRNQzR6Tnk5M2IzSmtjSEpsYzNNdiZzdz0xOTIwJnNoPTEwODAmY2Q9MjQmYWE9MSZzbD0yMDA0JnBwPTcyNjcmcGw9Zmxhc2h8
Use burp to send packets
From the Mysql Log, we can see that the single quotation mark is included in the query
Because there is no output point, union is not allowed, and only blind injection is allowed.
Append the guessing key program
<?php$ci = "YToyOntzOjEyOiJjb250ZW50X3R5cGUiO3M6NDoiaG9tZSI7czo4OiJjYXRlZ29yeSI7czowOiIiO30=";$nonce="ae93e0c4e2f76695c4dd540456ab7945";for($secret=time();$secret>1136044800;$secret--){ if($nonce==md5($ci.md5($secret))){ echo "find the secret is ".md5($secret); break; } }?>