首页 > 解决方案 > 即使我们正在清理输入 mysql_real_escape_string 的 SQL 注入漏洞代码

问题描述

我们被攻击了;黑客从下面显示的代码中的 <login> 页面进入系统,但我们无法找出这段代码中的实际问题。

您能否指出此代码中的问题以及可能的修复方法?

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

    ?>

标签: phpsqlsecuritysql-injectionowasp

解决方案


这里的问题在于$pass= hash("sha1",$pass, true);

你需要这样写$pass= hash("sha1",$pass, false);

一个不错的选择是迁移到 PDO。


让我们看看为什么会这样:

您的代码正在做的是返回一个原始二进制哈希,这意味着在某个时间点哈希可能包含一个相等的字符=,例如,在这种情况下导致 SQL 注入的哈希是"ocpe"因为 hash ("ocpe",sha1 )有一个'='字符,但我怎么能弄清楚呢?

您只需要运行一个简单的蛮力并测试它是否包含'='内部散列原始位。

这是一个简单的代码,可以帮助您

<?php
$v = 'a';
while(1)
{
        $hash = hash("sha1",$v, true);
        if( substr_count( $hash, "'='" ) == 1 ) {
            echo $v;
            break;
        }
        $v++;
}

?>

现在你有一个字符串,它给出了一个内部相等的哈希'='

查询变为:

$query = "select user, pass from users where user='$user' and pass='hash("ocpe",sha1)'";

然后

$query = "select user, pass from users where user='$user' and pass='first_Part_of_hash'='Second_part_of_hash'";

在这种情况下,我假设ocpe字符串具有这种格式的哈希first_Part_of_hash'='Second_part_of_hash

因为pass='first_Part_of_hash'将导致0and0='Second_part_of_hash'由 SQL 引擎进行类型转换,但是string如果我们将其类型转换为 aint它将给出 0 ((int)'Second_part_of_hash'结果是0
所以最后0=0

$query = "select user, pass from users where user='$user' and 0=0";

每次都会导致“真”,如您所见,它可以应用于所有哈希函数,如 MD5 和 sha256 等。


检查的好资源:

如何防止 PHP 中的 SQL 注入?

散列可以防止 SQL 注入吗?


推荐阅读