Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL injection vulnerable code even when we are sanitizing the input mysql_real_escape_string

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'";
        //...

    ?>
like image 468
joey Avatar asked Apr 04 '19 18:04

joey


1 Answers

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?

like image 88
zerocool Avatar answered Nov 14 '22 21:11

zerocool