如何在PHP中安全地实现"记住我"按钮(持久登录)

nic*_*ick 11 php security cookies session

首先是一些背景,我还在学习PHP,我正在尝试建立一个CMS(免责声明:仅供我自己使用).

我还在测试一些东西,并且我已经成功创建了一个管理员登录系统.

所以,现在这就是它的工作原理:

  • 在验证和清理输入后,用户登录,检查用户是否存在,并使用PHP password_verify将密码与存储在DB中的散列密码进行比较.

  • 如果登录成功,我将管理员重定向到a dashboard.php并创建一个名为的会话变量adminId,并将用户ID存储在该变量中.

这是我的第一个问题:

攻击者能否改变$_SESSION['adminId']?的价值?例如,从1更改为12,因此以不同的管理员身份登录?

无论如何,我读过这篇介绍攻击者可以使用的多个漏洞的文章.

所以,如果我没有错,我应该使用cookie进行持久登录吗?

好吧,首先要做的是永远不要将用户ID存储在cookie中并使用它来检查登录,因为攻击者可以很容易地改变它吗?

很好,所以我可以创建一个随机令牌(使用random_bytes然后转换为十六进制)并将其logins与数据库中的表中的用户ID配对.

例如,我有这个:

token: 2413e99262bfa13d5bf349b7f4c665ae2e79e357,
userId: 2
Run Code Online (Sandbox Code Playgroud)

因此,用户登录时,会创建令牌,并使用userId存储在数据库中.假设用户关闭了浏览器.然后他再次打开它,所有它都是带有令牌的cookie:2413e99262bfa13d5bf349b7f4c665ae2e79e357.所以,它会自动使用userId:2登录用户吗?

如果他想以userId:10为用户登录,他需要知道与该用户配对的随机令牌.

很好,但后来出现了这个问题:定时泄漏.所以他们提出了一个使用两个东西的解决方案,一个选择器和一个验证器 这是我不理解的时候,这就是文章所说的:

以下是我们提出的在Web应用程序中处理"记住我"cookie而不向攻击者泄露任何有用信息(甚至是时间信息)的策略,同时仍然快速有效(以防止拒绝服务攻击).

我们提出的策略在一个关键方面偏离了上述简单的基于令牌的自动登录系统:token我们存储的不仅仅是在cookie中存储随机数selector:validator.

selector是一个便于数据库查找的唯一ID,同时防止不可避免的时序信息影响安全性.(这比仅使用数据库id字段更好,这会泄漏应用程序上活动用户的数量.)

在此输入图像描述

在数据库方面,validator没有存储批发; 相反,SHA-256哈希validator存储在数据库中,而明文存储(用selector)在用户的cookie中.有了这种故障安全措施,如果某个auth_tokens表被泄露,就会阻止立即广泛的用户模仿.

自动登录算法类似于:

  1. 独立selectorvalidator.
  2. 抓住auth_tokens给定选择器的行.如果没有找到,则中止.
  3. validator使用SHA-256对用户cookie提供的哈希值进行哈希处理.
  4. 使用我们生成的SHA-256哈希值与数据库中存储的哈希值进行比较hash_equals().
  5. 如果步骤4通过,则将当前会话与相应的用户ID相关联.

所以这就是我不明白的地方:

1)应该采取什么selectorvalidator包含哪些内容?
2)为什么这个系统是安全的以及它如何防止定时泄漏?

在此先感谢,对于长篇文章感到抱歉,但我真的想了解这是如何工作的,我该如何实现它.

我知道我可以使用一些框架或库,但我想从scracth,通过反复试验来学习它!

Mat*_*t S 8

攻击者能否改变$_SESSION['adminId']?的价值?例如,从1更改为12,因此以不同的管理员身份登录?

不会.会话数据仅存储在服务器上.客户端只有标识会话的字符串.

我应该使用cookie进行持久登录吗?

如果您要进行持久登录,通常就是这样做的.

所以第一件事是永远不要将用户ID存储在cookie中并使用它来检查登录,因为攻击者可以很容易地改变它吗?

正确,您永远不会想要暴露任何关键数据,例如用户ID.

1)应该采取什么selectorvalidator包含哪些内容?

每个都是正确生成的随机字符串(例如使用openssl_random_pseudo_bytes).的selector必须是唯一的.

2)为什么这个系统是安全的以及它如何防止定时泄漏?

它增加了两个安全功能,而不是生成一个基本令牌并直接查找.

首先,如果您的数据库泄露给攻击者他们无法生成他们自己的记住我的cookie并冒充每个用户.在validator只存储在数据库中作为一个散列值.cookie必须包含未散列的值.反转好的哈希是非常耗时的.

其次,比较仅在服务器上生成的哈希可以避免计时攻击.如果攻击者发送各种记住我的cookie值来定时查找,它就不会暴露任何有用的东西,因为服务器上的比较是针对散列值而不是原始值.

一般来说,如果您的系统的安全性非常重要,我建议您不要支持记住我的功能.如果您确实要在重要站点上使用此功能,请使用已经过测试的库以确保安全.