this loophole was found in 2014, in the spirit of learning, I will do a detailed analysis. Although the vulnerability is early, the new version of Drupal has even changed the way the framework is organized. However, the analysis of the vulnerability is not affected at all. This is a classic use of PDO, but improperly handled, resulting in SQL statement stitching resulting in injection problems. Judging from this and many of the loopholes I've seen in the past, I have to say that the bottom line of the code is safe and filtered completely, and if the programmer is careless, it will also lead to significant security issues. The number of coding bypasses, the logical loophole is the problem caused by carelessness.
0x00 injected positioning
First I follow the exp that has already appeared on the network, then carries on the tracking. Helpless, this framework is too big, I am in the process of follow-up, encountered a lot of problems, even the route mode is not very clear. Then, based on the details of the loopholes, I quickly targeted the point of occurrence of the vulnerability.
in the file \modules\user\user.module, there are the User_login_authenticate_validate () function has the following code:
functionUser_login_authenticate_validate ($form, &$form _state) { $password=Trim($form _state[' Values '] [' Pass ']); if(!Empty($form _state[' Values '] [' Name ']) &&!Empty($password)) { //Do not allow any of the login from the current user's IP if the limit has been//reached. Default is failed attempts allowed in one hour. This is//independent of the per-user limit to catch attempts from one IP to log//in to many different user Accou Nts. We have a reasonably high limit//Since there is only one apparent IP for all users at an institution. if(!flood_is_allowed (' Failed_login_attempt_ip ', Variable_get (' User_failed_login_ip_limit ', '), Variable_get (' User_ Failed_login_ip_window ', 3600))) { $form _state[' flood_control_triggered '] = ' IP '; return; } $account= Db_query ("select * FROM {users} WHERE name =: Name and status = 1",Array(': name ' = =$form _state[' Values '] [' name '])) -Fetchobject (); //omit irrelevant code ...
Obviously, the SQL query here is the vulnerability trigger scene, we follow db_query This function, the code is as follows:
functionDb_query ($query,Array $args=Array(),Array $options=Array()) { if(Empty($options[' Target '])) { $options[' target '] = ' default '; } returnDatabase::getconnection ($options[' Target ']) ->query ($query,$args,$options);}
Continue to follow the query function:
Public functionQuery$query,Array $args=Array(),$options=Array()) { //Use the default values if not already set. $options+=$this-defaultoptions (); Try { //We allow either a Pre-bound statement object or a literal string. In either case, we want-to-end up with a executed statement object,//which we pass to pdostatement::execute. if($queryinstanceof Databasestatementinterface) { $stmt=$query; $stmt->execute (NULL,$options); } Else { $this->expandarguments ($query,$args); $stmt=$this->preparequery ($query); $stmt->execute ($args,$options); } //omit irrelevant code ...
We know that if we use PDO to precompile in a PHP connection to MySQL database, our statement cannot change the original query structure, that is, the injected statement cannot be queried, only as a string. This provides a thorough defense of the injection from the database query layer. So how does this make a problem?
Security issues caused by the processing of 0x01 errors
But there is a problem here, that is, when the parameter is an array, the Expandarguments method is used, and this method can cause security problems due to improper handling.
The function code is as follows:
protected functionExpandarguments (&$query, &$args) { $modified=FALSE; //If The placeholder value to insert was an array, assume that we need//to expand it out into a comma-delimited set of placeholders. foreach(Array_filter($args, ' Is_array ') as $key=$data) { $new _keys=Array(); foreach($data as $i=$value) { //This assumes, there is no other placeholders that use the same//name. For example, if the array placeholder are defined as:example//And there is already an:example_2 placeholder, thi s would generate//a duplicate key. We do the calling code//are already broken if that happens. $new _keys[$key. ‘_‘ .$i] =$value; } //Update the query with the new placeholders. Preg_replace is necessary to ensure the replacement does not affect//placeholders so start with the same exact Text. For example, if the//query contains the Placeholders:foo And:foobar, And:foo have AN//array of values, USI Ng Str_replace would affect both placeholders,//But using the following preg_replace would only Affect:foo because It is followed by a non-word character. $query=Preg_replace(‘#‘ .$key. ' \b# ',implode(‘, ‘,Array_keys($new _keys)),$query); //Update the args array with the new placeholders. unset($args[$key]); $args+=$new _keys; $modified=TRUE; } return $modified; }
Let's review the previous query statements,
Db_query ("select * FROM {users} WHERE name =: Name and status = 1", Array (': name ' = = $form _state[' values ' [' name ']))
This array we are controllable, first after Array_filter, using foreach to traverse, and then a new array is created in the two-wheel traversal. Then the key in the $query variable is replaced, and the later content is replaced with a new string that is merged into the new array key with ', '. That way we can do SQL injection through the keys. The injected statement will be entered by stitching.
0X03 test
It can be seen clearly that the two keys in the name array are stitched into the SQL query.
0x04 Reflection
Here is a very interesting, but also very common problem. I also said it in the preface to the beginning. It was done, but the stitching was used, resulting in a controllable external data entry into the SQL query. Similar problems are common, of course, this also provides a way for themselves to dig holes, in the increasingly difficult to dig holes in the present, the change of the hole thinking is very important.
Drupal V7.3.1 framework improperly processing results in SQL injection