We have been attacked; the hackers entered the system from a page <login> that's in the code shown below, but we couldn't figure out the actual problem in this code.
Could you point out the problem in this code and also a possible fix?
<?php
//login.php page code
//...
$user = $_POST['user'];
$pass = $_POST['password'];
//...
mysql_connect("127.0.0.1", "root", "");
mysql_select_db("xxxx");
$user = mysql_real_escape_string($user);
$pass = mysql_real_escape_string($pass);
$pass = hash("sha1", $pass, true);
//...
$query = "select user, pass from users where user='$user' and pass='$pass'";
//...
?>
The problem here is in $pass= hash("sha1",$pass, true);
You need to put it like this $pass= hash("sha1",$pass, false);
A good option is to move to PDO.
Let's see why this happen:
What your code is doing is returning a raw binary hash that means at a point in time the hash may contain an equal character =
,
for your example the hash that going to result in SQL injection in this case is "ocpe"
because hash ("ocpe",sha1) have a '='
character,
but how can I figure that out?
You only need to run a simple brute force and test if it contains a '='
inside the hash raw bit.
This is a simple code which can help you with that
<?php
$v = 'a';
while(1)
{
$hash = hash("sha1",$v, true);
if( substr_count( $hash, "'='" ) == 1 ) {
echo $v;
break;
}
$v++;
}
?>
Now you you have a string that gives a hash that has an equal inside of it '='
The query becomes:
$query = "select user, pass from users where user='$user' and pass='hash("ocpe",sha1)'";
then
$query = "select user, pass from users where user='$user' and pass='first_Part_of_hash'='Second_part_of_hash'";
In this case I assume that ocpe
string has a hash of this format first_Part_of_hash'='Second_part_of_hash
Because pass='first_Part_of_hash'
going to result in 0
and 0='Second_part_of_hash'
is typecasted by the SQL engine, but in case of string
if we type cast it to a int
it's going to give as 0 ((int)'Second_part_of_hash'
is result in 0
)
so in the end 0=0
$query = "select user, pass from users where user='$user' and 0=0";
Which going to result in "true" every time and as you can see it can be applied to all hash functions like MD5 and sha256 etc.
Good resources to check:
How can I prevent SQL injection in PHP?
Could hashing prevent SQL injection?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With