问题1:
我可以使用$userid = mysql_real_escape_string($_GET['user_id']);
或者我需要使用下面的代码更好?
function mysql_prep( $value ){
$magic_quotes_active = get_magic_quotes_gpc();
$new_enough_php = function_exists( "mysql_real_escape_string" ); //example. php >= v4.3.0
if( $new_enough_php ) { //php v4.30 or higher, undo any magic quote effects so mysql_real_escape_string can do the work
if( $magic_quotes_active ) { $value = stripslashes( $value );}
$value = mysql_real_escape_string( $value );
} else { //before php v4.3.0.
if( !$magic_quotes_active ) { $value = addslashes( $value ); }
}
return $value;
}
$userid = trim(mysql_prep($_GET['user_id']));
问题2:我们真的需要在md5()
上使用shal()
或$_SESSION['user_id']
吗?为什么我们需要那个?会话劫持者只能得到会话ID,但他不能得到会话变量值吗?如果是这样,那么我不需要再散列$_SESSION['user_id']
的值吧?例如:
if (isset($_POST['login'])) {
if ($username==$user_username_in_db && $hashed_password==$user_password_in_db) {
$_SESSION['user_id'] = sha1($user_id_in_db); //sha1 convert userid to crazy long characters
}
}
$query2 = "SELECT id FROM user WHERE sha1(id)='{$userid}' LIMIT 1";
问题3:由于php会话劫持发生且我无法负担使用ssl / https,所以我让网站每次尝试删除邮件或朋友时都要求用户提交密码,因为会话劫持者可能会冒充用户删除他的消息/朋友。如果我的网站总是要求用户输入密码,我可以知道这是危险的吗?密码会更容易被黑客攻击?我是否知道会话劫持者只能冒充用户,但不能正确窃取用户的密码?
答案 0 :(得分:8)
问题1:如果您的user_id在数据库中存储为整数,则可以使用:
$user_id = intval($_GET['user_id']);
因此,如果有人篡改了查询字符串,那么可能发生的一切就是他们得到一个空白的结果。但是,目前还不清楚你如何使用$ _GET ['user_id'];
问题2:sha1和md5是散列算法。这意味着对于任何长度的任何给定字符串,它们会返回一个显示为41/32字节十六进制字符串的数字。
有什么用?使用的是那些算法不可逆,这使得它们非常适合隐藏某人的用户名和密码等信息。 许多人为所有事情使用同一个密码,以确保他们的密码不会被盗,以防你搞砸了,黑客可以访问你的数据库 - 你为用户提供了另一个级别的安全性 - 没有人 能够从哈希中获取实际密码。当然,这也可以防止有权访问数据库的人阅读人的密码并破坏他们的隐私。 现在,有办法尝试将哈希转换为纯文本(所谓的彩虹表),但这是另一个主题。
问题3:您实际上应该首先防止会话劫持。为什么会这样?您是否以某种方式(通过URL)向公众公开session_id并且您正在实施标准检查吗?
偶尔询问密码对用户来说是一种烦恼,应该避免,除非你想不出保护会话的方法。
至于其他东西,还有一些叫做PHP PDO的东西,理论上应该使用清理字符串,连接到数据库并将内容更容易地插入到数据库中(虽然它比普通的mysql_或者相当复杂) mysqli_函数所以人们似乎避免它)。您至少应该阅读它以了解它的作用以及它如何帮助您防止SQL注入。
答案 1 :(得分:1)
问题1:我可以使用$ userid = mysql_real_escape_string($ _ GET ['user_id']);
是和否。
是的,因为你不需要下面的所有代码。
不,因为 mysql_real_escape_string与安全无关 它不会使数据“安全”,也不会“消除注射”,也不会“转换危险字符” 但只是逃避字符串分隔符 就是这样 如此。
mysql_set_charset()
函数设置编码。您可以使用预准备语句,而不是将数据直接放入字符串中。
(惊喜!)SQL安全性不仅限于此功能用法。还有很多其他问题。
答案 2 :(得分:0)
您绝不应以纯文本格式保存密码。您最好使用MD5或SHA1。使用其中之一的优点是没有人可以“解密”密码,这只是一种“单向”加密。
答案 3 :(得分:0)
始终使用绑定参数而不是转义以防止SQL注入攻击。转义可以工作,但它容易出错:不同的数据库有不同的转义规则,您可能会因为错误的规则集而无意中逃脱,留下可以利用的空白。如果将参数值与查询字符串分开,则恶意参数值不可能更改查询结构。 PHP data objects是在PHP中执行此操作的正确方法。
我没有看到哈希存储在会话中的用户ID。散列内容的通常原因是为了防止看到散列的人知道“原始”值是什么,但是$_SESSION
中存储的内容无论如何都不会显示给用户。如果您使用的是register_globals
,那么通过在查询字符串中添加$user_id
参数来欺骗引用user_id
的代码的人可能是一种防御,但这可以被规避(攻击者)可以将目标user_id
的哈希值放在他们的查询参数中),不管怎样你都不应该使用register_globals
(正是出于这些原因)。
要求用户更频繁地输入密码意味着必须更频繁地通过网络传输密码。由于您没有使用SSL,这意味着它被窃听的风险增加。还有其他方法可以避免会话劫持,例如在会话中存储用户的IP地址,如果具有该会话ID的请求来自不同的IP,则丢弃会话。
您还可以实施对OpenID的支持,以替代密码身份验证。如果您使用密码,则应该只在数据库中存储salted哈希值,这样如果有人设法获取密码表的副本,则无法恢复用户的实际密码。