PHP Sessions + Useragent with salt

时间:2009-03-05 20:49:26

标签: php user-agent salt session-hijacking

在过去的几天里,它一直在我的脑海中运行,但我读了一些关于如何使PHP会话更安全的文章。几乎所有这些文章都说你需要在会​​话中使用额外的盐来保存useragent。像这样:

$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']);

盐会使攻击者更难以劫持或无论什么会话。但是,为什么每次检查时都加盐:

md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']) == $_SESSION [ 'fingerprint' ]

为什么盐会让它更安全,因为攻击者仍然只需要使用者(相对来说是一小组不同的使用者)和sessionid?

可能是我忽视的一些小东西,但无法弄明白,让我疯狂哈哈

谢谢!

9 个答案:

答案 0 :(得分:7)

建议添加盐的原因很简单。通常,当您创建此“指纹”时 - 如果您只使用一个具有有限数据集的数据项,则外部黑客可以更轻松地生成此数据并劫持会话。

在上面的示例中,是的,如果攻击者同时具有“指纹”和用户代理,则他们将能够劫持会话。

添加盐只会让攻击者更难以生成指纹,这是“如果他们只拥有一条信息,那么最后一条信息就会变得毫无用处”。

我建议您添加更多内容,例如,在vBulletin(我曾经使用过的项目)中,使用以下代码生成会话ID哈希(与指纹基本相同)。

define('SESSION_IDHASH', md5($_SERVER['HTTP_USER_AGENT'] . $this->fetch_substr_ip($registry->alt_ip))); // this should *never* change during a session

此外,使用

生成会话哈希
md5(uniqid(microtime(), true));

尝试识别会话时都会检查这些

因此,要劫持会话,该人需要知道以下内容

  • 创建会话时服务器上的时间(确切)
  • 用户浏览器代理字符串
  • 用户的IP地址

他们还必须欺骗IP地址(或至少前2/3个八位字节)才能做到这一点。

如果他们实际上已经设法获得上述信息,那么他们可能会以其他方式进行攻击,而不仅仅是会话劫持。

vBulletin实际上并没有实际使用“盐”,但是,在上面的例子中,盐只是添加了有限量的熵,最好找到尽可能多的熵。

例如,在我目前用python编写的东西中,我生成了一个用于XSRF保护的哈希。以下是我使用的内容。

    self.key = sha1(
        self.user.username +
        self.user.password +
        settings.SECRET_KEY +
        strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
    ).hexdigest()

使用用户的用户名和密码,当前时间和预设盐来生成此信息。这对于攻击者来说很难生成由于盐和时间(但是请注意,这只是因为一旦使用它就会变得安全,随着时间的推移,这对于某人来说并不需要太多如果它没有改变,请为特定用户破解这个)

答案 1 :(得分:3)

如果您在自己的服务器上,加密会话变量毫无意义,因为它们不会离开服务器。有关详细信息,请参阅What do I need to store in the php session when user logged in? Linead 回答。如果您在共享服务器中,除了会话ID之外,您可能还需要加密每个会话变量,因为它们存储在您的所有邻居正在使用的同一Web服务器可读的临时文件中。

无论如何,如果你真的担心安全问题,你最好使用自己的(虚拟或非虚拟)服务器,因此危险只会来自服务器外部。

会话风险的一些例子:

  • 您的服务器在URL中发送会话ID,并且您的用户跟随到badguys.com的链接。他们将在服务器变量中获取引用者(完整的URL,包括您的会话ID),浏览器和您的用户的IP地址。如果您没有检查IP,或者您的用户使用开放代理,他们只需要安装相同的浏览器版本,粘贴URL就可以了。
  • 用户去公共电脑,登录,离开而不关闭他的会话(嘿,他毕竟是人)。该行中的下一个人打开浏览器,检查历史记录并找到一个打开的会话。呸。

所以,根据我的惯例,你可以采取一些措施:

  1. 不要在网址中发送会话ID;在PHP中启用session.use_only_cookies。缺点:用户需要启用cookie。
    • 关于危险操作(更改密码,下订单......),再次询问用户密码。你也可以定期做。缺点:烦人。
    • 快速超时会话。缺点:在大多数网站中,这将迫使用户经常登录,使他们烦恼。
    • 使用SSL(唯一的方法是避免'中间人'攻击)。缺点:慢。愚蠢的浏览器消息。在服务器上需要SSL。
    • 检查IP。缺点:对使用公共代理的访问者无效。烦恼动态IP。
    • 检查用户代理(浏览器)。缺点:非常无用,UA很容易获得并且很容易模仿。
  2. (我认为你已经配置了PHP以获得最大的安全性。)

    一些更极端的措施:

    • 维护服务器和浏览器之间的永久连接,例如使用Java小程序。没有连接,没有会话。缺点:用户需要Java,ActiveX或您使用的任何东西。会话以浏览器关闭(这可能很好)。不适用于非常慢的连接。服务器负载较高。您需要打开端口,为applet配备一个特殊的服务器。
    • 同样,但使用异步请求(例如AJAX)非常频繁地刷新会话,并且超时很短。或刷新隐藏的IFRAME。缺点:用户需要JavaScript。不适用于非常慢的连接。服务器上的负载更高。
    • 同样,但重新加载整个页面。缺点:用户需要JavaScript。在您阅读页面时自动重新加载非常令人讨厌。

    在某些极端情况下,您可以忘记会话并使用Apache身份验证。最简单的解决方案,但有很多限制。

答案 2 :(得分:2)

如果我理解正确,您希望阻止猜测会话ID的远程攻击者进行会话劫持?

如果不是这种情况,那么你就会严重超出你的范围 - 可以窥探流量的攻击者也可以模仿用户代理,并且无论如何攻击者都可以访问你的会话存储。

如果存储用户代理字符串以将会话“锁定”到当前用户代理,那么散列它就没有意义 - 完整用户代理字符串上的字符串比较更快(然后散列然后比较)和在存储方面没有那么昂贵。

我不认为存储用户代理提供了足够的区别 - 更好的方法是在会话开始时生成更大的ID(具有更多位)(也许sha1当前时间戳+用户名+用户代理+东西),然后将其存储在cookie和会话中,并在每个附加请求中匹配它。这并没有太大地改变攻击向量(你仍然需要猜测一些数字),但是通过大量增加攻击的难度,它很容易显着增加必须猜测成功攻击的位数。

答案 3 :(得分:1)

我看到了腌制指纹的一个目的。如果一个坏人抓住你的session-db(上帝知道原因)而不是你的代码,他就不能通过尝试针对它的普通用户代理来“猜测”你的指纹识别方法。

答案 4 :(得分:0)

我也是partially protect from session impersonation attacks那样做的。您还需要包含IP地址。

请记住,当客户端的浏览器自动更新用户代理更改时,您会认为他的会话已被劫持;)

答案 5 :(得分:0)

由于指纹存储在服务器端,因此您无需使用盐渍哈希。 “正常”散列足以减少数据。

答案 6 :(得分:0)

请记住,如果你这样做,那么如果他们升级浏览器,就会强迫别人再次登录。这可以,但只是确保这是你的意图。

使用用户的远程地址也不是没有问题。许多人使用来自不同位置的同一台计算机。移动设备,家庭和工作中使用的笔记本电脑,Wifi热点使用的笔记本电脑等。恕我直言,使用IP地址是一个坏主意,新IP地址需要登录,除非您正在处理高度敏感的信息,如网上银行。是这样的吗?

你在乎什么?外部攻击?或者在共享主机情况下,有人可以阅读您的会话信息?

如果是后者,解决方案很简单:只是不要在会话中存储任何敏感内容。任何敏感的东西都应该存储在数据库中。

在创建秘密盐方面,您需要使用不可猜测的东西。我会选择在创建用户时创建的随机字符串。如有必要,每次会话无效时重新创建它。

至于它会使它更安全,你自己说:用户代理字符串有限(不到一百个可能会覆盖99.99%的用户)。盐只会增加可能性的数量。话虽这么说,如果你在所有会话中使用相同的盐,那么在用蛮力发现它之前只是时间问题。

答案 7 :(得分:0)

好的,例如我正在使用以下虚构代码:

<?php

// The sessionid cookie is now a certain hash
if ( array_key_exists ( $_COOKIE [ 'sessionid' ] ) )
{
    // Get the session from database
    $db_sessid = $pdo -> getStuff ( 'session_database', $_COOKIE [ 'sessionid' ] );

    if ( $db_sessid !== null && $db_sessid [ 'fingerprint' ] == sha1 ( 'SOMESALT' . $_SERVER [ 'HTTP_USER_AGENT' ] ) )
    {
        set_cookie ( ... ); // New sessionid and write also to DB

        // User is now logged in, execute some user stuff
    }
    else
    {
        // Session doesn't exist, or the fingerprint does not match
    }
}

现在攻击者仍然需要sessionid,它位于cookie中(沿HTTP标头发送)和useragent。那么附加盐还有什么意义呢?

在我看来,检查IP也不是一个好的选择,一些提供商或代理商会在每次请求时更改它们。

到目前为止感谢( - :

答案 8 :(得分:-2)

在满足所有safegard参数之后,您才允许cookie设置一个cookie,如果不满足该参数,cokkie将永远不会被设置为好,但是如果cookie具有可见的参数,那会发生什么。同样,如果条件从未满足,那么会议将得到满足。这就是您真正想要的。记住检查是否符合条件,以便通过Cookie提供会话和查看数据 记住,cokkie坐在客户浏览器上 问候Stelios