PHP - 会话标识符 - 安全性

时间:2017-05-10 16:58:16

标签: php security session ssl session-variables

我对使用全局$_SESSION[]变量有疑问。

目前,无论用户何时登录我的网络应用程序,都会返回与该用户名匹配的行以及该特定密码。然后,我会获得user_hash列并将user_hash存储在$_SESSION['id']中。

我使用此会话来识别哪个用户已登录并基于此唯一哈希执行数据库查询。我读到某个地方有一个"静态"像这样的标识符(静态标识符是user_hash,因为它永远不会改变)是不安全的,我宁愿让user_hash动态地改变。

所以我实现了一个系统,每当用户登录和/或导航到Web应用程序中的某个其他页面时,我会生成一个新的哈希值,将其存储在数据库中,然后将其存储在全局{{1变量。我设法做到了这一点,但现在每当有人试图从两个设备登录时,设备都会使用" old"会话无效,因为user_hash已从新设备更改并使用较旧的会话注销用户。

我的问题是,这样做有什么意义吗?我正在为我的网络服务器使用ssl(https),所以我认为会话劫持相对不在桌面上?如果只有一个静态会话标识符存在安全漏洞,是否有更好的方法使其成为动态,而同时不关闭其他用户?

1 个答案:

答案 0 :(得分:1)

两个有用的链接

http://blog.teamtreehouse.com/how-to-create-bulletproof-sessions

https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions

  

我设法做到了这一点,但是现在每当有人试图从两个设备登录时,具有“旧”会话的设备都无效,因为user_hash已从新设备更改并使用旧会议。

虽然这可能是不必要的,具体取决于您的安全要求,但我在上面发布的first link说明了这一点:

  

将旧会话标记为已过时,并将其标记为在十秒内[或适合您需要的某个时间]过期。这样,任何排队的请求仍然可以访问过期的会话,但我们不必永远保持打开状态。

static function regenerateSession()
{
    // If this session is obsolete it means there already is a new id
    if(isset($_SESSION['OBSOLETE']) || $_SESSION['OBSOLETE'] == true)
        return;

    // Set current session to expire in 10,30,100 seconds etc.
    $_SESSION['OBSOLETE'] = true;
    $_SESSION['EXPIRES'] = time() + 10; //or 30 seconds or whatever.

    // Create new session without destroying the old one
    session_regenerate_id(false);

    // Grab current session ID and close both sessions to allow other scripts to use them
    $newSession = session_id();
    session_write_close();

    // Set session ID to the new one, and start it back up again
    session_id($newSession);
    session_start();

    // Now we unset the obsolete and expiration values for the session we want to keep
    unset($_SESSION['OBSOLETE']);
    unset($_SESSION['EXPIRES']);
}
  

所以我实现了一个系统,每当用户登录和/或导航到Web应用程序中的某个其他页面时,我会生成一个新的哈希值,将其存储在数据库中,然后将其存储在全局$ _SESSION ['id']变量。

从个人角度来说,我怀疑它非常无效,并且会导致服务器负载的大量开销不断重新发明。这是不需要的。

如果您真的想重新发布会话,只需使用session_regenerate_id()并将其设置为时间值(例如每10分钟),如outlined in the first link所示,位于此帖的顶部。

重要的唯一值是会话标识会话数组中的所有值都不会被浏览器或最终用户看到

因此;只要您的会话ID是 LONG 随机值,它就会隐藏在视线范围内。从second link above获取更多关于如何确保PHP为您提供更多随机和更长命名会话ID的保留。

的php.ini

session.save_handler = files
session.use_cookies = 1
session.cookie_secure = 1
session.use_only_cookies = 1
session.cookie_domain = "example.com"
session.cookie_httponly = 1
session.entropy_length = 32
session.entropy_file = /dev/urandom
session.hash_function = sha256
session.hash_bits_per_character = 5  

如果在数据库中存储会话,请确保为会话ID设置足够长的列名,否则会话将永远不会因会话名称的截断而连接。

其他一些因素

  • 确保PHP的会话cookie设置为encrypted。无论您的TLS连接状态如何,都必须手动完成此操作。见上文session.cookie_secure=1

  • 您可以通过添加浏览器或ip特定数据(例如这些相应$_SERVER值的哈希值)来帮助最小化已经不太可能的hjack事件,以便在执行任务时进行比较会话,比较浏览器类型/客户端IP仍然与会话记录中的内容进行比较。这两种方法中的每一种都可能存在问题,例如移动连接上的少数人可能在登录期间更改IP,或者多个设备上的用户可能每个都有不同的浏览器,但是找到一种方法可以根据需要进行比较 (这也在页面顶部的first link中引用)

  • 如上所述,$_SESSION数据永远不会存储在客户端计算机上,因此数据库中要存储在$_SESSION中的散列值很可能超出了您的安全需求。

  • (单个)最重要的是会话ID是安全的,足够大,可以轻松容纳潜在的黑客钓鱼假冒会话ID作为在我的世界上玩战列舰的亲属