如何增强网站的安全性?

时间:2011-04-26 15:26:26

标签: php mysql

问题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,所以我让网站每次尝试删除邮件或朋友时都要求用户提交密码,因为会话劫持者可能会冒充用户删除他的消息/朋友。如果我的网站总是要求用户输入密码,我可以知道这是危险的吗?密码会更容易被黑客攻击?我是否知道会话劫持者只能冒充用户,但不能正确窃取用户的密码?

4 个答案:

答案 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_real_escape_string属于引用数据,没有别的。
  • 仍有一些关于编码的挑剔,因此,如果您要使用它,您应该始终使用mysql_set_charset()函数设置编码。
  • 您可以使用预准备语句,而不是将数据直接放入字符串中。

  • (惊喜!)SQL安全性不仅限于此功能用法。还有很多其他问题。

  • 整体网站安全不仅限于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哈希值,这样如果有人设法获取密码表的副本,则无法恢复用户的实际密码。