用户登录时,我需要在php会话中存储什么?

时间:2009-08-03 09:39:49

标签: php security session

目前,当用户登录时,我创建了2个会话。

$_SESSION['logged_in'] = 1;
$_SESSION['username']  = $username; // user's name

那么,那些需要登录的页面,我只是这样做:

if(isset($_SESSION['logged_id'])){
// Do whatever I want
}

是否存在安全漏洞?我的意思是,攻击我的会话容易吗?人们如何破解会话?以及如何防止它?

编辑:

刚刚发现:

http://www.xrvel.com/post/353/programming/make-a-secure-session-login-script

http://net.tutsplus.com/tutorials/php/secure-your-forms-with-form-keys/

刚刚找到链接,这些方法是否足够好?请提出你的意见。我还没有得到最好的答案。

9 个答案:

答案 0 :(得分:45)

术语

  • 用户:访客。
  • 客户端:安装在特定计算机上的特定网络软件。

了解会话

为了了解如何确保会话安全,您必须首先了解会话的工作方式。

让我们看看这段代码:

session_start();

一旦你调用它,PHP就会寻找一个名为PHPSESSID的cookie(默认情况下)。如果找不到,它将创建一个:

PHPSESSID=h8p6eoh3djplmnum2f696e4vq3

如果找到,则取PHPSESSID的值,然后加载相应的会话。该值称为session_id

这是客户唯一知道的事情。无论您添加到会话变量中的是什么,都会保留在服务器上,并且永远不会转移到客户端。如果更改$_SESSION的内容,则该变量不会更改。它会一直保持不变,直到你摧毁它或它超时。因此,尝试通过对其进行散列或通过其他方式对$_SESSION的内容进行模糊处理是没有用的,因为客户端从未接收或发送该信息。

然后,在新会话的情况下,您将设置变量:

$_SESSION['user'] = 'someuser';

客户永远不会看到这些信息。


问题

恶意用户窃取其他用户的session_id时可能会出现安全问题。如果没有某种检查,他就可以自由地冒充该用户。我们需要找到一种方法来唯一地识别客户端(而不是用户)。

一种策略(最有效)涉及检查启动会话的客户端的IP是否与使用会话的人员的IP相同。

if(logging_in()) {
    $_SESSION['user'] = 'someuser';
    $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}

// The Check on subsequent load
if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR']) {
    die('Session MAY have been hijacked');
}

该策略的问题在于,如果客户端使用负载均衡器,或者(在长时间会话中)用户具有动态IP,则会触发虚假警报。

另一个策略涉及检查客户端的用户代理:

if(logging_in()) {
    $_SESSION['user'] = 'someuser';
    $_SESSION['agent'] = $_SERVER['HTTP_USER_AGENT'];
}

// The Check on subsequent load
if($_SESSION['agent'] != $_SERVER['HTTP_USER_AGENT']) {
    die('Session MAY have been hijacked');
}

该策略的缺点是,如果客户端升级其浏览器或安装插件(一些添加到用户代理),则用户代理字符串将更改,并将触发虚假警报。

另一种策略是在每5个请求上轮换session_id。这样,session_id理论上不会长时间被劫持。

if(logging_in()) {
    $_SESSION['user'] = 'someuser';
    $_SESSION['count'] = 5;
}

// The Check on subsequent load
if(($_SESSION['count'] -= 1) == 0) {
    session_regenerate_id();
    $_SESSION['count'] = 5;
}

您可以根据需要组合这些策略中的每一种,但您也会将缺点结合起来。

不幸的是,没有任何解决方案是万无一失的。如果您的session_id遭到入侵,那么您已经完成了很多工作。上述策略只是权宜之计。

答案 1 :(得分:13)

这太荒谬了。

会话劫持发生在(通常是通过跨站点脚本攻击)某人拦截您的sessionId(这是一个由浏览器自动发送到Web服务器的cookie)。

有人发布了这个例子:

  

所以当用户登录时:

     

//不是最安全的哈希!   $ _SESSION ['checksum'] =   MD5($ _ SESSION [ '用户名'] $盐);

     

在进入敏感区域之前:

     

if(md5($ _ SESSION ['username']。$ salt)   != $ _SESSION ['checksum']){
  handleSessionError(); }

让我们看看这个

的错误
  1. 盐 - 没错,但毫无意义。没有人会破坏你该死的md5,谁在乎它是否被腌制
  2. 将SESSION变量的md5与存储在SESSION中的同一变量的md5进行比较 - 您将会话与会话进行比较。如果东西被劫持,这将无济于事。
  3. $_SESSION['logged_in'] = 1;
    $_SESSION['username']  = $username; // user's name
    $_SESSION['hash']      = md5($YOUR_SALT.$username.$_SERVER['HTTP_USER_AGENT']);
    
         

    //用户姓名哈希避免   操作

    避免被谁操纵?神奇的会议精灵?除非服务器受到损害,否则不会修改会话变量。哈希只是真正将你的字符串很好地压缩成48个字符的字符串(用户代理可以有点长)。

    至少我们现在正在检查一些客户端数据,而不是检查SESSION到SESSION数据,他们检查了HTTP_USER_AGENT(这是一个识别浏览器的字符串),这可能足以保护你,但是你我必须意识到,如果这个人已经在某个时候已经开始使用你的sessionId,那么你很可能也会向坏人服务器发送一个请求并给你的用户代理坏人,所以聪明的黑客会欺骗你的用户代理并破坏这种保护

    你是什么意思到了这个可悲的事实。

    一旦您的会话ID被泄露,您就会离开。您可以检查请求的远程地址,并确保在所有请求中保持相同(正如我所做的那样),这对于99%的客户群来说都是完美的。然后有一天你会接到一个使用带有负载平衡代理服务器的网络的用户的电话,请求将通过一组不同的IP(有时甚至在错误的网络上)从这里发出,他将会失去他的会话左右中心。

答案 2 :(得分:1)

您可以在PHP here中找到有关会话安全性的指南。

答案 3 :(得分:1)

您可以通过javascript(XSS-> crossside脚本攻击)窃取会话。您应该始终使用 salted MD5哈希来保护您的会话。

为避免会话劫持,您应该使用用户代理

  

$ _ SERVER [ 'HTTP_USER_AGENT']

也是哈希。

在你的例子中:

$_SESSION['logged_in'] = 1;
$_SESSION['username']  = $username; // user's name
$_SESSION['hash']      = md5($YOUR_SALT.$username.$_SERVER['HTTP_USER_AGENT']); // user's name hashed to avoid manipulation

在使用会话之前,请确保它使用正确的哈希:

if (!$_SESSION['hash']==md5($YOUR_SALT.$username.$_SERVER['HTTP_USER_AGENT'])){
  die ('session hash not corrected')
}

答案 4 :(得分:1)

您可以存储IP地址,浏览器签名等以识别用户。 在每个请求中,根据当前值检查它以查看是否发生了任何可疑事件。

请注意,有些人支持使用绝对动态IP地址的提供商,因此这些人可能会经常登出。

答案 5 :(得分:1)

我猜第二个需要'logged_in'?

有关会话安全的一些资源:

phpsec

shiflett

答案 6 :(得分:1)

防止会话固定,这基本上是猜测SID或使用各种方法窃取它。无论你的会话逻辑多么复杂,它肯定会在某种程度上容易受到偷窃行为的攻击。这就是为什么每次做重要事情时都必须重新生成ID。例如,如果您要在管理员中发帖或更改设置,请首先运行session-regenerate-id。然后黑客必须再次经历黑客入侵的过程。这基本上可以让黑客一次性使用身份证一次性浪费。

http://us.php.net/manual/en/function.session-regenerate-id.php

或者您可以随时更改ID

if($ _ SESSION ['counter'] == 3){session_regenerate_id(); $ _ SESSION ['counter'] == 0}

另外,$ _SERVER ['HTTP_USER_AGENT']不太可靠。尽量避免它,不仅仅是因为这个原因,而且因为它对黑客来说很方便,因为他们知道代理商已广泛使用它。而是尝试使用$ _SESSION ['id_token'] = sha1(一些疯狂的信息,如文件内存,文件名,时间)。

答案 7 :(得分:0)

这是通常的登录代码,可以进行一些改进以使其更难破解。首先,您可以使用用户名和登录时间进行校验和,或者使用预定义的字符串(或盐),并将其存储在会话中,并进行比较。

所以当用户登录时:

// not the most secure hash!
$_SESSION['checksum'] = md5($_SESSION['username'].$salt); 

在进入敏感区域之前:

if (md5($_SESSION['username'].$salt) != $_SESSION['checksum'])
{
  handleSessionError();
}

默认情况下,会话通常作为文件存储在服务器端,并在用户的浏览器上放置cookie以记住要引用的文件。当谈到会话黑客时,黑客通过使用来自cookie的信息以某种方式检索足够的信息以复制登录或管理以更改会话数据。

您可以使用数据库编写自己的会话处理代码以增加安全性。一些更严格的CMS,如Joomla,也记录了IP。但是,这会导致使用某些ISP的人员出现问题

答案 8 :(得分:0)

当我在构建SugarCRM时遇到此问题时,我跟踪并验证了用户的IP地址(除了其他一些内容)。我只比较了IP地址的前三个部分。这允许大多数本地可变IP地址。我还可以关闭IP地址的主要变化很常见的安装的IP地址验证。我认为只比较IP地址的开头可以帮助您提高安全性,而不会对您的应用程序造成如此严重的限制。

示例:“###。###。### .---” 只会验证标有“#”的IP地址部分。

192.168.1.101
192.168.1.102
192.168.1.XXX

都被认为是平等的。

雅各