我们被攻击了;黑客从下面代码中的
您能否指出此代码中的问题以及可能的修复方法?
<?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'";
//...
?>
最佳答案
这里的问题在$pass= hash("sha1",$pass, true);
你需要这样写 $pass= hash("sha1",$pass, false);
迁移到 PDO 是一个不错的选择。
让我们看看为什么会这样:
你的代码正在做的是返回一个原始的二进制散列,这意味着在某个时间点散列可能包含一个相等的字符 =
,
对于您的示例,在这种情况下导致 SQL 注入(inject)的散列是 "ocpe"
因为散列 ("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'
将导致 0
和 0='Second_part_of_hash'
由 SQL 引擎进行类型转换,但在string
的情况,如果我们将其类型转换为 int
,它将给出 0((int)'Second_part_of_hash'
是 中的结果>0
)
所以最后 0=0
$query = "select user, pass from users where user='$user' and 0=0";
每次都会产生“true”,正如您所见,它可以应用于所有哈希函数,如 MD5 和 sha256 等。
值得检查的好资源:
关于php - SQL 注入(inject)易受攻击的代码,即使我们正在清理输入 mysql_real_escape_string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55522941/