我们受到了什么攻击,
那些黑客从一个下面显示代码的页面进入系统,但我们无法弄清楚这段代码中的实际问题.
你能指出这个代码中的问题,还有可能解决的问题
<?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注入的哈希是“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引擎进行类型化,但是在字符串的情况下,如果我们键入将它转换为int,它将给出为0((int)’Second_part_of_hash’结果是0)
所以最后0 = 0
$query = "select user, pass from users where user='$user' and 0=0";
每次都会产生“真实”,正如您所看到的,它可以应用于所有散列函数,如MD5和sha256等.
好的资源来检查:
How can I prevent SQL injection in PHP?
Could hashing prevent SQL injection?