在创建新网站时,我需要新的登录脚本,这样我就可以放心地使用我的数据了。我早些时候做过这样的脚本,但谁知道它们有多安全。希望能在网上找到一些答案,我发现了这样一个教程,它自称为"超级安全登录脚本"。你可以在这个链接中找到它
我想知道它到底有多安全,它容易受到什么样的威胁。
我还在代码行中发现了这样的内容:
// Create Second Token
$tokenId = rand(10000, 9999999);
$query2 = “update users set tokenid = $tokenId where userid = ‘$_SESSION[userid]‘”;
$result2 = mysql_query ($query2);
$_SESSION['token_id'] = $tokenId;
它应该如何工作?它阻止了什么?我应该将$_SESSION['token_id']与稍后的内容进行比较吗?
您发布的代码只是创建一个随机数,然后将其存储在用户数据库表中的用户记录中,然后存储在会话中。根据提供的链接,令牌或随机数实际上根本不会用于任何事情。您必须向开发人员询问其含义。
我不推荐您链接到的登录脚本,原因如下:
1) 它逃避用户输入以避免SQL注入的方式
以下是所使用的功能:
function escape_data ($data) {
// Check for mysql_real_escape_string() support.
// This function escapes characters that could be used for sql injection
if (function_exists(‘mysql_real_escape_string’)) {
global $dbc; // Need the connection.
$data = mysql_real_escape_string (trim($data), $dbc);
$data = strip_tags($data);
} else {
$data = mysql_escape_string (trim($data));
$data = strip_tags($data);
}
// Return the escaped value.
return $data;
} // End of function.
上述函数存在一些问题。最大的是,如果它发现mysql_real_escape_string()
不存在,它就会回落到mysql_escape_string()
。您永远不应该回到mysql_escape_string()。如果mysql_real_eescape_string()不可用,并且您依赖它来避免SQL注入,那么您的应用程序应该停止。另一个问题是它使用了strip_tags()
。SQL注入的转义和XSS的转义/编码是两件不同的事情,不应该合并为一件。
我建议使用MySQLi准备的语句或PDO参数化查询来代替此函数,以避免SQL注入。
为了避免XSS,每当打印出源于用户输入的数据库内容(或直接用户输入)时,请使用htmlentities()
。
2) 这是不好的做法
$_SESSION[userid] // this should have single quotes, making it $_SESSION['userid']
3) PHP逻辑和HTML混合在一起,不需要将它们分开。
4) 登录表单上的CAPTCHA。这只会让用户不高兴。通常登录表单上不需要CAPTCHA
编辑-我在这里回应了您在评论中的一些观点
作者对代币的意图
这真的是任何人的猜测,但也许这个随机数是用来重置密码的链接。对于这类事情,通常会对随机数/字符串进行哈希处理,而不是保留一个短的随机数。此外,mt_rand()比rand()要好。
使用单一函数进行SQLi转义和XSS预防
这是个坏主意,因为它们是两种截然不同的东西。SQLi的转义是在数据库的入站完成的,如果你明白我的意思,XSS预防应该在出站完成。
在数据库中存储数据时,通常最好以原始形式存储,而不是使用strip_tags()或htmlenties()。如果在某个时刻,出于任何原因,您希望允许HTML输入数据库,该怎么办?
XSS预防应该在数据从数据库中出来并进入页面或进入任何位置时进行。如果你想将数据输出到HTML以外的另一种介质,如XML或web服务,并且你已经将其处理为HTML,该怎么办。XSS和SQLi的单个函数并不能使代码更干净,它将过程应用于当时不需要应用的数据。
看看任何流行的框架,如Zend,或CMS,如WordPress,Joomla等。它们都没有为SQLi和XSS使用单个函数。
混合PHP和HTML
是的,你是对的,这不会影响安全,但看起来很糟糕。它很难阅读,很难维护,很难扩展和更新,这无疑是我不推荐它的原因
$_SESSION['userid']
中的报价
在查询中使用$_SESSION[userid]
来解决由于引用而导致的查询中断问题,表明缺乏知识/经验。
您可以使用引号,只需要像一样将变量连接到查询中
$sql = "SELECT * FROM table WHERE something = '" . $_SESSION['something'] . '";
当然,如果您不确定变量的内容,则需要转义SQLi(最好使用参数化查询)。
CAPTCHA
CAPTCHA在正确的地方使用非常好。像这样的登录表单不是其中之一。你可以在X次尝试失败后使用CAPTCHA(就像谷歌一样),但不是像这样一直需要它。还有其他处理暴力登录尝试的方法,SO.上有几个答案
我没有提到的另一点是密码散列。那就是使用不含盐的SHA1,这不是很强。我会使用SHA256或更高版本,并使用salt作为密码。