PHP会话的安全性

时间:2013-01-14 14:39:57

标签: php security session suhosin

我知道这已被问过数十亿次,但我对于编码的安全性我是超级偏执/强迫症。我正在做一个小项目。会话数据仅包含:

  

user_id 1
   user_name MyUsername
   logged_in 是真的    csrf_token 87cc51ee94178df79cccce2aebc45d53

这是我的代码。是否安全足以在小型CMS上使用?

session_start();

ini_set('session.cookie_httponly', 'On');
ini_set('session.cookie_secure', 'On');
ini_set('session.use_cookies', 'On');
ini_set('session.use_only_cookies', 'On');

$rand = rand(1, 10);

if ($rand != 1 || $rand != 3 || $rand != 5)
    session_regenerate_id();

$user_ip = md5($_SERVER['REMOTE_ADDR']);
$user_agent = md5($_SERVER['HTTP_USER_AGENT']);

if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) {
    $session_user_ip = $_SESSION['user_ip'];
    $session_user_agent = $_SESSION['user_agent'];

    if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) {
        unset($_SESSION);
        session_destroy();

        die('Error');
    }
} else {
    $_SESSION['user_ip'] = $user_ip;
    $_SESSION['user_agent'] = $user_agent;
}

然后召集会议:

$_SESSION['user_id'] = 1;
$_SESSION['user_name'] = 'MyUsername'; // etc.

额外信息
我将使用会话数据来检查用户是否有权执行某些操作。示例:if ( user_has_perm( $_SESSION['user_id'] ) )

提前感谢您的帮助。

7 个答案:

答案 0 :(得分:12)

会话安全风险来自三种不同的可能性:

  • 预测
  • 捕获
  • 固定

预测意味着不是创建会话的用户的某个人会猜到他们的会话ID。发生这种情况的可能性几乎为0,尽管随着越来越多的用户同时使用该网站,它们确实会增长。

使用您的代码,您可以将风险降低,因为只有在攻击者共享用户代理和预测会话的IP时才会起作用。但在这种情况下,差异是微不足道的。

修复意味着攻击者可以创建会话,然后强制其他用户使用他们的会话。在这种情况下,它将取决于:如果攻击者知道您正在执行此操作并伪造用户代理和客户端的IP,则他们可以修复会话。或者,如果他们共享ip和用户代理。

最后我们有会话劫持,这可能是三者中最常见的方法。在这种情况下,攻击者会以某种方式获得对有效登录用户的会话ID的访问权限,然后使用它登录到他们的帐户。与前面的方法一样,只有当他们知道您正在检查ip和用户代理并伪造与用户相同的方法时,这才适用于他们。您使用的技术并不是唯一的,一些攻击者可能会伪装它们以防万一。


话虽如此,它是否安全? 且没有

如果您对安全性着迷,答案总是一样的:使用SSL

除非你的代码是开源的,否则你所做的几乎所有改变php会话的行为都是足够安全的。

唯一的例外是非常受欢迎的网站,它们会引起黑客的注意。

有关此主题的一些非常好的文档:

答案 1 :(得分:3)

我不是安全专家。但是,我谦卑地怀疑您的安全执行会带来实质性的好处。

如果有人可以窃取用户的会话ID,例如通过窃听未加密的无线网络,我打赌他还可以窃取用户在进行身份验证时发送给服务器的用户名和密码。一旦获得访问凭据,攻击者就可以在一天之后或一周后登录,并且可以使用他的“安全” - 并且100%有效的会话。

我认为没有通道安全性就没有会话安全性。如果您使用SSL ,您确保会话ID仅通过Cookie发送(您已经在使用Cookie)并且您的会话很快就会过期,我相信您相当安全,并且比执行这些操作更安全在不安全的渠道上。

答案 2 :(得分:2)

首先,会话重新生成代码时出错。以下if将始终评估为true:

if ($rand != 1 || $rand != 3 || $rand != 5)

如果$rand 1,则返回true。如果$rand 1,那么它不是三,它返回true。你可能想在这里使用and

其次,您不需要MD5 user_ipuser_agent字符串。如果有人可以直接访问您服务器上的会话数据,那么您就可以深入了解数据无法保存的哈希值。

澄清:正如SDC和crush在评论中指出的那样,如果您使用salt 对其进行散列,则MD5适用于散列密码。这意味着即使SQL注入攻击成功并且您的数据库暴露给全世界,您的用户密码通常仍然是安全的。 但是,如果您的服务器遭到入侵,并且盐被泄露,则可以生成一组已知的哈希值,并尝试反向查找特定密码。底线?用盐哈希你的用户密码。

第三,大多数安全漏洞并非来自欺骗会话。他们来自糟糕的输入检查。像Essential PHP Security这样的书应该是对PHP项目中应该进行的输入检查的一个很好的介绍。如果做不到这一点,至少要阅读security section of the PHP Manual。注意SQL注入位。真酷!

最后,我完全赞同您应该使用SSL来保护与您网站的通信的另一张海报。

答案 3 :(得分:0)

说实话,我认为你过于谨慎,但不是很有用。

如果您真的担心会话安全,请不要自己尝试。使用像Suhosin这样的PHP安全补丁。让它为您完成所有艰苦的工作。 Suhosin是一个完善的PHP补丁。它包含处理PHP会话被攻击的所有方式的东西。如果您已经安装了它,那么您不需要做任何额外的事情来保护您的会话。如果你没有安装它,那么你绝对不能声称对安全性超级偏执!

简而言之,安装Suhosin(如果你还没有),就忘了它。

但为了完整起见,我会在您的实际代码中发表一些评论,只是指出一些事情:

我不确定为什么你认为MD5散列有任何区别。 MD5哈希值可以在几秒钟内破解,因此将它们置于任何类型的安全功能中都是完全随意的。它也可以是纯文本。也就是说,我并不是真的认为除了纯文本之外还需要它们 - 如果黑客已经设法获取会话数据以便能够读取它包含的IP地址,那么你& #39;已经不必担心他们是否知道IP地址。

答案 4 :(得分:0)

它们只是两个主要的会话攻击

1。)会话固定攻击。

这可以通过使用session_regenerate_id()

来防止

2。)会话劫持:

这可以通过使用SSL证书进行数据加密来防止。您的网站现在将在 https 而不是 http 上运行。

3。)如果您在未实现CloudFare或JailRoot的共享服务器上。您可以显示将会话存储在数据库中,而不是使用默认文件系统存储。

有了这三个实现,让我看看声称声称黑客使用者会话的黑客...

答案 5 :(得分:-1)

选择要上传的图片:                                                                                                   &#34 ;;         $ res = mysql_query(" SELECT`id`,`FirstName`,`LastName`,`Address`, `密码`,`Repassword`,`生日`,`性别`,`user_image` FROM `registration`")或die(mysql_error());         而($行= mysql_fetch_array($水库))         {             $ ID = $行[' ID'];             $姓名= $行['姓'];             $ user_image = $行[' user_image']; $页=&#34。                                   $名字&#34 ;;             } $页=&#34。                                                                                                                                                                                                                                                                                                                                                                                                                                                                    &#34 ;;                 $ res_post = mysql_query(" SELECT post_info.post_info_id, post_info.id,post_info.post_info_desc,registration.FirstName FROM`post_info` 加入`registration` WHERE post_info.id = registration.id order by post_info.post_info_id desc")或die(mysql_error());                     而($ row_post = mysql_fetch_array($ res_post))                     {                     $ post_id = $ row_post [' post_info_id'];                     $ post_desc = $ row_post [' post_info_desc'];                     $ id = $ row_post [' id'];                     $ FirstName = $ row_post [' FirstName'];             $页="

$姓

$ post_desc

&#34 ;;                     } $页=&#34。                    &#34 ;;       包括('包括/ main_file.php&#39);     ?>

答案 6 :(得分:-2)

<?php

session_start();
$con=mysql_connect("localhost","root","");
$seldb=mysql_select_db('myfreind', $con);
$email=$_POST['txtEmail'];
$password=$_POST['txtPass'];
$res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`, `Repassword`, `Birthday`, `Gender` FROM `registration` WHERE 
`Password`='$password' and  `FirstName`='$email'");
$num=mysql_num_rows($res);

if($num==1)
{
$row=mysql_fetch_array($res);
$id=$row['id'];
$firstname=$row['FirstName'];
$_SESSION['id']=$id;
$_SESSION['FirstName']=$firstname;
//echo $_SESSION['id'];
header('Location:main.php');
}else

{

header('Location:index.php?error');
}

?>