pdo和hash来防止sql注入


pdo and hash to prevent sql injection

可能重复:
防止PHP 中SQL注入的最佳方法

我正在尝试将用户的输入插入数据库中
这个pdo和hash足够安全吗:

$dbh = new PDO("mysql:host=hostName; dbname=dbName", "user", "pass");
if(isset($_POST['Submit']))
{
$user = $_POST['user'];
$pass = $_POST['pass'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($pass, '$2a$12$' . $salt);
$mail = $_POST['mail'];
$confirm_key=md5(uniqid(rand()));
$sth = $dbh->prepare("INSERT INTO members(user, pass, mail, confirm_key)
VALUES ('$user', '$hash', '$mail', '$confirm_key')");
$sth->execute();

对于什么是SQL注入以及为什么要对密码进行散列,您似乎有点困惑。

密码散列(和salting)是为了使数据库包含足够的信息来验证密码,但不足以检索密码。如果攻击者获得对数据库的(离线)访问权限,她仍然无法在不破解安全散列的情况下读取任何密码。为此,您的代码看起来是合理的。

SQL注入是一个完全不同的野兽。该漏洞的工作原理是向PHP代码发送值,当这些值插入到动态SQL查询中时,会以有趣的方式打断它,这样查询现在就可以做一些与预期不同的事情。例如,用户可以为$user提供一个值,使INSERT查询保持有效,但会打断引用的字符串并添加第二个查询,这可能会造成危害,例如用已知值覆盖其他用户的密码哈希,之后攻击者可以登录到他们想要的任何帐户(包括管理帐户)。

防范SQL注入的最佳方法是通过参数化查询,PDO提供开箱即用的查询;但是您没有使用它们,所以您的代码很容易受到攻击。阅读PDO参数化查询的文档;如果你不确定它们是如何工作的,可以回来再次询问。

您正在滥用准备好的语句,请将代码更改为:

$stmt = $dbh->prepare("INSERT INTO members(user, pass, mail, confirm_key) VALUES (:user, :hash,:mail,:confirm)");
$stmt->bindParam(':user', $user);
$stmt->bindParam(':hash', $hash);
...

请参阅此处了解更多详细信息。