PHP中正确的会话劫持预防

Posted

技术标签:

【中文标题】PHP中正确的会话劫持预防【英文标题】:Proper session hijacking prevention in PHP 【发布时间】:2012-01-15 04:50:01 【问题描述】:

我知道这个话题已经讨论了很多,但是我还有一些具体的问题没有得到解答。例如:

// **PREVENTING SESSION HIJACKING**
// Prevents javascript XSS attacks aimed to steal the session ID
ini_set('session.cookie_httponly', 1);

// Adds entropy into the randomization of the session ID, as php's random number
// generator has some known flaws
ini_set('session.entropy_file', '/dev/urandom');

// Uses a strong hash
ini_set('session.hash_function', 'whirlpool');

// **PREVENTING SESSION FIXATION**
// Session ID cannot be passed through URLs
ini_set('session.use_only_cookies', 1);

// Uses a secure connection (HTTPS) if possible
ini_set('session.cookie_secure', 1);

session_start();

// If the user is already logged
if (isset($_SESSION['uid'])) 
    // If the IP or the navigator doesn't match with the one stored in the session
    // there's probably a session hijacking going on

    if ($_SESSION['ip'] !== getIp() || $_SESSION['user_agent_id'] !== getUserAgentId()) 
        // Then it destroys the session
        session_unset();
        session_destroy();

        // Creates a new one
        session_regenerate_id(true); // Prevent's session fixation
        session_id(sha1(uniqid(microtime())); // Sets a random ID for the session
    
 else 
    session_regenerate_id(true); // Prevent's session fixation
    session_id(sha1(uniqid(microtime())); // Sets a random ID for the session
    // Set the default values for the session
    setSessionDefaults();
    $_SESSION['ip'] = getIp(); // Saves the user's IP
    $_SESSION['user_agent_id'] = getUserAgentId(); // Saves the user's navigator

所以,我的问题是

ini_set 是否提供足够的安全性? 是否可以保存用户的IP和导航器然后查看 每次加载页面时检测会话劫持?这会不会有任何问题? session_regenerate_id() 的用法正确吗? session_id() 的用法正确吗?

【问题讨论】:

所有夸大的随机性可能是安全性中最不相关的部分,因为最广泛的安全漏洞通常完全在其他地方。你也只需要在登录成功时重新生成会话ID。 嗯,不会有伤害的。另外,我这样做的一个主要原因是因为我的网站上没有帐户,只有匿名导航。因此,没有登录之类的东西。 每次都重新生成会话ID会更好吗? 没有唯一的答案。首先是在登录时重新生成。除此之外有点矫枉过正。不知何故,会话再生在某些情况下可能会有所帮助。示例:如果您管理某种事务(保存帖子、上传文件、在应用程序后面更改数据),这会有所帮助,因为您可以跟踪用户是否执行了历史记录 (-1) 并再次发送了旧请求。 关于重新生成:在用户的权限更改时任何重新生成。虽然这包括跨越登录/注销障碍时的重新生成,但它还应该包括任何时候授予或撤销用户任何类型的应用程序权限或角色更改。 不要认为它是完整的,但你可能会发现它作为一个勾选列表很有用***.com/questions/8318944/… 【参考方案1】:

您的配置很棒。您肯定阅读了如何锁定 php 会话。然而,这行代码否定了您的 php 配置提供的许多保护: session_id(sha1(uniqid(microtime()));

这是一种特别糟糕的生成会话 id 的方法。根据您的配置,您正在从 /dev/urandom 生成会话 ID,这是一个很棒的熵池。这将比 uniqid() 随机得多,后者已经主要是一个时间戳,在这个组合中添加另一个时间戳根本没有帮助。尽快删除这行代码。

检查 IP 地址是有问题的,IP 地址更改是出于正当原因,例如用户在负载均衡器或 TOR 后面。用户代理检查是没有意义的,就像有一个像?is_hacker=False 这样的 GET 变量,如果攻击者有会话 id,他们可能有用户代理,如果他们没有这个值很容易暴力破解。

【讨论】:

很好的答案.. 我同意,如果您已经知道会话 ID,IP 可以是真正动态的,并且导航器信息很容易被伪造,但是越安全越好(除非花费很多资源,在这种特殊情况下它没有)。但是,我可能会将$_SESSION['ip'] !== getIp() || $_SESSION['user_agent_id'] !== getUserAgentId() 更改为$_SESSION['ip'] !== getIp() && $_SESSION['user_agent_id'] !== getUserAgentId()。如果两个条件都满足,那么肯定会发生一些奇怪的事情。无论如何感谢您的回答! @John Doe 是的,这不是一个坏主意。如果您检测到任何类似的禽兽游戏,您可能只想破坏会话以防止攻击者试图欺骗他的用户代理。如果他搞砸了一次,那就不要再给他机会了。 没错!如果他是真正的用户,他一开始就不会和用户代理搞混,所以销毁他的会话是安全的 @John Doe 你也应该阅读 CSRF,又名“Session Riding” 也可以使用前两组IP地址xxx.xxx。不太安全,但总比没有安全,大型大学和企业的问题也更少。

以上是关于PHP中正确的会话劫持预防的主要内容,如果未能解决你的问题,请参考以下文章

session劫持以及预防

取消Mediawiki登录以防止会话劫持

简书网页劫持分析,网站劫持,利用 CSP 预防劫持

逆向调试简书网页劫持分析,使用 Chrome DevTools 调试 JavaScript 技巧,利用 CSP 预防劫持

Java核心面试宝典Day20如何进行DNS劫持并预防?

Java核心面试宝典Day20如何进行DNS劫持并预防?