This article mainly introduces the data about the bypass vulnerability caused by the character offset feature in PHP, the paper not only introduces the formation of the loophole, but also introduces the repair method, which has certain reference value for the students, and needs the friends to take a look at them.
Character offset properties in PHP
The string in PHP has a very interesting feature, and the string in PHP can be evaluated like an array.
$test = "Hello World"; Echo $test [0];
The final result is H.
But the above characteristics sometimes have unexpected effects, see the following code
$mystr = "Hello World"; Echo $mystr ["Pass"];
The output of the above code is H. What is this for? In fact, as in many other languages, strings can be used as arrays in PHP. The $mystr["pass"] pass is converted to 0 by the implicit type, so $mystr[0] the output is the first letter H.
Similarly, if you try the following code:
$mystr = "Hello World"; Echo $mystr ["1pass"];
The result is E. Because the 1pass is converted to 1 by the implicit type, $mystr[1] the output is the second letter E.
Vulnerabilities caused by character attributes
The following code is used in phpspy2006 to determine which code to use when logging in.
$admin [' check '] = "1"; $admin [' pass '] = "Angel", ... if ($admin [' check '] = = "1") {...}
Such validation logic can easily be bypassed if the above features are used. $admin is not initially defined as an array type, when we commit with a string phpsyp.php?admin=1abc , PHP takes the first bit of the string 1xxx and successfully bypasses the IF condition judgment.
The above code is a code fragment, the next piece of code is a complete logic code, from the Php4fun in the 5th question, more interesting.
<?php# goal:overwrite password for admin (id=1) # Try to login as admin# $yourInfo =array (//this are your user data in The db# ' id ' + 8,# ' name ' = ' jimbo18714 ', # ' pass ' = ' maybechanged ', # ' level ' = ', ' ' Level ', ' require '; f Unction MREs ($str) {return mysql_real_escape_string ($STR);} $userInfo = @unserialize ($_get[' userInfo '); $query = ' SELECT * from users WHERE id = \ '. MREs ($userInfo [' ID ']). ' \ ' and pass = \ '. MREs ($userInfo [' Pass ']). '\';'; $result = mysql_query ($query); if (! $result | | mysql_num_rows ($RESULT) < 1) {die (' Invalid password! ');} $row = Mysql_fetch_assoc ($result), foreach ($row as $key = = $value) {$userInfo [$key] = $value;} $oldPass = @$_get[' Oldpass '); $newPass = @$_get[' Newpass '];if ($oldPass = = $userInfo [' Pass ']) {$userInfo [' pass '] = $newPa ss $query = ' UPDATE users SET pass = \ '. MREs ($newPass). ' \ ' WHERE id = \ '. MREs ($userInfo [' ID ']). '\';'; mysql_query ($query); Echo ' Password Changed ';} else {echo ' Invalid old password entered. ';}
This topic on the net only gives a final answer, the principle of which is not said or not to say very detailed. In fact, the principle is the above mentioned PHP character characteristics.
The problem is simple to change the admin password, admin ID is 1. Here are a few questions that we need to consider:
How to change the ID to 1 at the time of update
$userInfo['pass'] = $newPass;What does this line of code do, and why this code exists in the IF Judgment statement
Having figured out these two issues, the final solution is also there. Change the password of the user with ID 8 to 8, then pass in a userinfo string ' 8 ', break through the query protection, and finally use $userInfo['pass'] = $newPass the ID to change to 1.
The ultimate payload is;
First commit, the index.php?userInfo=a:2:{s:2:"id";i:8;s:4:"pass";s:12:"MAYBECHANGED";}&oldPass=MAYBECHANGED&newPass=8 purpose is to change the password of the user with ID 8 to 8
The second commit, index.php?userInfo=s:1:"8";&oldPass=8&newPass=1 so serialization $userinfo get is the string ' 8 ', that is $userInfo = ‘8' , so that database query validation can pass. After the if validation can also pass through this line of code $userInfo['pass'] = $newPass; , because the value of $newpass is 1, then the above code becomes $userInfo['pass'] = 1; , $userInfo because of a string type, finally, the last is to update the password of the $userInfo='1' user ID 1.
How to fix
The remedy for this vulnerability is also simple, and it is best to check that the data type used is consistent with the expected data type when it is used in a predefined manner. Otherwise, the above-mentioned bypass problem will occur. At the same time to control the input, the input data to be checked and do not use arbitrarily.