在 PHP 中使用会话和 cookie 创建安全登录

Posted

技术标签:

【中文标题】在 PHP 中使用会话和 cookie 创建安全登录【英文标题】:Creating a secure login using sessions and cookies in PHP 【发布时间】:2011-07-23 01:07:35 【问题描述】:

我正在制作一个我希望尽可能安全的登录脚本。问题是,安全似乎是一场永无止境的战斗。所以本质上,我正在寻找建议和改进我的想法。

我所拥有的是仅基于会话的登录。每当会话信息发生变化时,都会调用session_regenerate_id() 以避免明显的劫持尝试。

当会话未设置时,我检查 cookie 是否有效登录,并在成功时更新会话。

我尝试通过添加一个哈希值以及一条独特的用户信息(如用户名或 ID)来保护 cookie。这个散列由各种信息组成,包括用户名/id、无法破译的密码散列、部分 IP 地址等。通过从 cookie 中提取用户名/id,我可以从有效的用户信息中创建一个新的散列并比较它使用 cookie 中的哈希。我的希望是防止虚假 cookie 和 cookie 劫持(除非他们也欺骗 IP 地址)。

编辑假设登录本身将通过 HTTPS/SSL 完成,因此传输是(相当)安全的。

我在正确的轨道上吗?还可以做些什么来保护我的登录?

感谢您的帮助!

【问题讨论】:

phpseclib.sourceforge.net 对于未来的安全相关主题(只是加了书签!)知道这实际上非常好,但我假设如果传输是安全的,那么将使用 SSL。我更多的是寻找保护登录状态的想法,以防止通过不道德的方式未经授权的进入。 使用 SSL 怎么样?归根结底,如果攻击者在同一个网络上并且正在嗅探,我认为没有所有这些帮助,而且 SSL 也并非完全牢不可破,但至少它不是明文。我的 2c 除非用户明确要求您这样做,否则您不应将会话绑定到 IP 地址。 1.我只绑定了部分 IP 地址 2:为什么不呢? (请注意,包含 IP 部分的哈希是这样完成的,因此我无法破译 IP 地址或哈希中的任何其他组件,因此,我无法使用该信息来跟踪它们)。 【参考方案1】:

停止你正在做的事情。不要检查user-agent 或IP 地址。用户代理是攻击者控制的变量,检查这个值不会增加这个系统的安全性。 ip 地址会因正当原因而更改,例如用户在负载均衡器或 TOR 后面。

会话 ID 必须始终为 cryptographic nonce。在 php 中只需调用 session_start() 然后开始使用 $_SESSION 超级全局。 PHP 会为您处理所有这些。如果您想改进 php 的会话处理程序,请使用configurations。启用use_only_cookiescookie_httponlycookie_secure。如果您在 *nix 系统上,但如果您在 Windows 下,那么将 entropy_file 设置为 /dev/urandom 也是一个好主意,那么您就有麻烦了。

例如对用户进行身份验证:

//In a header file
session_start();
...
if(check_login($_POST['user_name'],$_POST['password']))
   //Primary key of this user
   $_SESSION['user_id']=get_user_id($_POST['user_name']);
   $_SESSION['logged_id']=True;

并验证用户是否登录:

//in a header file
session_start()
...
if(!$_SESSION['logged_id'])
   header("location: login.php");
   die();//The script will keep executing unless you die()

要改进此系统,请阅读 OWASP A9 并在会话的整个生命周期中使用 HTTPS。另请阅读 OWASP A5: CSRF aka "session ride" 和 OWASP A2: XSS,因为它们都可以用来破坏会话。

【讨论】:

这一切都很棒,而且在很大程度上正是我正在做的事情。但是饼干呢?我用它来记住会话之间的登录,因此用户不必每天分别登录 5 次。 @steveo225 session_start() 为您创建一个 cookie。可以通过配置php来更改过期时间。 是的,我意识到这一点,但我不想设置持续数天……甚至数周的过期时间。 @steveo225 平台需要一个过期时间,因为如果你没有这个漏洞,它就是一个漏洞,它被称为不朽会话。请记住,此值可能是暴力破解的,并且没有速率限制器,甚至没有日志。 这就是我的观点。我不希望会话持续那么久,所以我使用 cookie 来“刷新”会话,作为保持用户登录的一种手段,只要我认为合适。因此,据我所知,我正在做几乎所有正确的事情来保护会话并维护登录详细信息,但是,我想制作一个非常难以复制、伪造、劫持等的“安全”cookie。 【参考方案2】:

没有安全 cookie 之类的东西,除非它仅通过 SSL 传输。使用持久性非会话 cookie(比如记住我)时,可以通过完全按照您正在做的事情来减轻它,但不是以您想要做的方式。

您确实可以存储服务器变量,例如用户代理、IP 地址等(甚至是 javascript 变量),但它们仅适用于验证持久 cookie 数据是否与客户端的新连接匹配。 ip 地址不是一个好主意,除非您知道客户端(仅像您一样)不会在每次页面加载时都发生变化(a la AOL)。

现代网络浏览器和 LastPass 等 3rd 方服务可以存储登录凭据,只需要按键(有时甚至不需要按键)即可将数据发送到登录表单。持久 cookie 只适用于那些拒绝使用其他可用的东西的人。最后,不再需要持久的非会话 cookie。

【讨论】:

好的,所以基本上,我可以做一些事情来混淆cookie,使其更难伪造、破解、复制等,但最后,如果用户选择“记住我”,那就是如果连接不安全,他们确实有责任确保安全,而我对此无能为力......【参考方案3】:

我使用基于 cookie 的方法(使用 setcookie 函数)但是 ....

session_start();
...
if(check_login($_POST['user_name'],$_POST['password']))
   //Primary key of this user
   $_SESSION['user_id']=get_user_id($_POST['user_name']);
   $_SESSION['logged_id']=True;

...这些方法太糟糕了!!!!

我通过基于 cookie 的攻击来破解我的网站。

    我使用了 WebCruiser 漏洞扫描器的 cookie 选项,所以我在登录后获取了我的 cookie。 然后我在 cookie 上更改了一个简单的值 然后我点击保存cookie。 此时我单击左侧面板上的 webbrowser 查看,然后单击右键,然后单击刷新页面,因此我在没有使用带有用户名和密码的登录页面的情况下获得了我的管理页面。

因此,如果有人向您推送病毒以读取 IE 或 Firefox 的 cookie 历史记录,您会很高兴找到您的管理员用户并且密码可以被其他人使用。

那么如何解决这个问题呢?简单:将cookie与会话服务器或会话的cookie与会话服务器结合,或将会话与文件会话结合,或将cookie与文件会话结合...... 会很安全但是很慢:((((

【讨论】:

【参考方案4】:

我将所有登录数据保存在用户会话中,这样它就全部存储在服务器端。

我会在客户端 cookie 中存储的唯一内容是“自动登录”、“会话 ID”等内容

【讨论】:

【参考方案5】:

SESSION 比 cookie 更安全 我的建议是为当前尝试的登录创建一个唯一的 ID 喜欢:

$id = uniqid();
$_SESSION['username'.$id] = "something ...";

【讨论】:

具有索引用户 ID 的会话不会处理此问题(通过自动创建的唯一会话 ID 吗?)

以上是关于在 PHP 中使用会话和 cookie 创建安全登录的主要内容,如果未能解决你的问题,请参考以下文章

PHP 会话控制技术

PHP 会话变量的安全性如何?

PHP 会话的安全性如何?

php中的Session是什么

Cookie&&Session

如何使用php制作涉及会话cookie的注销页面?