存储用户密码(服务器端),将其连接到cookie - 安全问题

时间:2012-06-08 08:50:01

标签: php security session cookies session-hijacking

我正在尝试找到有关Cookie /会话和数据库数据的问题的安全解决方案。

我已经阅读了不同的文章,例如http://www.devshed.com/c/a/PHP/Sessions-and-Cookies/解释了不同的Cookie盗窃和会话固定方法,以了解我将面临的安全问题。

问题如下:我有DB表,用AES_ENTRYPT()存储数据,使用用户密码加密它们。这意味着,即使阅读信息,我也必须使用明文密码来解密数据。

如果我只将密码存储在$_SESSION变量中,这可能不会成为一个问题,但这会导致无法在多天内通过cookie保持登录状态。

换句话说,我必须将明文密码存储在cookie中(至少要使该功能保持登录状态)

现在,您可以使用salted MD5()或SHA-256()哈希作为标识符,而不是密码。但我不能用哈希来解密数据。这意味着我必须存储密码服务器端(在数据库中?还是有其他安全方式?),将其连接到标识符 - 但是有权访问的每个人都可以访问密码到数据库,可以直接解密那里的数据。

是否有一种安全的方法,连接我存储在cookie中的标识符,并将其连接到服务器存储的用户输入(密码/帐户名)whitout实际上给予可以访问数据库的人可以读取该数据库服务器端存储的用户输入?

要求是,即使在最糟糕的情况下,某人有数据库转储和cookie(但无法访问服务器RAM),该人无法访问用户密码并用它解密存储的数据。

为避免混淆,请回顾一下:

这不是用户标识问题 - 登录过程单独发生(通常的方式:密码/ logindata的md5()哈希)。我的问题是,userdata(如地址,姓名,电子邮件)是使用用户密码加密的。所以我需要登录密码来解密它们。如果用户只是登录,这没有问题,因为我在$ _POST数据中有密码,并且可以使用它。但登录后?一旦$ _POST或$ _SESSION消失,我就无法再次解密数据。


可能的解决方案

经过一些输入后,我可能想出办法 - 它不是很安全,但它应该运作良好:

(这与登录/用户身份验证过程分开,我只是指加密/密钥部分)

user registers OR changes password:

    generate a new hash out of $email and $password => $auth

    do NOT store $auth in the usertable, just keep it

    generate a new random key for the user => $key (only on registering, not on pw change)

    encrypt $key with $auth, storing it into the usertable

    encrypt all user data with $key

user logs in (or after registering / password change):

    generate $auth ($password + $email)

    set cookie with $auth as variable

user is logged in (cookie / session / after login):

    decrypt $key with $auth

    use $key for data encryption / decryption (serverside)

这里唯一的问题是如果有人可以获得$ auth,他们可以解密$ key然后解密数据。我正在考虑为每次登录生成一个新的$ auth,但如果旧的$ auth丢失,这会引发我如何解密密钥的问题。这与令牌之间的区别在于,这会添加另一个层,其中令牌不是加密密钥本身。无论如何,我认为解决方案是公共/私人密钥之外最接近我的意图。非常感谢你。

4 个答案:

答案 0 :(得分:1)

在您的用户表中有一个名为token的字段,当您第一次插入用户时,该字段可以是随机哈希...

$token = md5(uniqid(mt_rand(), true));

然后将用户ID和令牌存储在cookie中,您可以使用它来查找用户。

答案 1 :(得分:1)

据我了解您的要求,您无法存储客户端或服务器端的密码。因此,您根本无法存储它。让用户输入每个页面加载的密码。

您可以使用例如memcached或APC将内容存储在RAM中,或者创建您可以在服务器上与之通信的自己的软件。这不会为您提供更多增强的安全性,因为任何有权访问服务器的人(通过shell)都可以以与软件完全相同的方式请求密码。在我看来,它破坏了“无文件,无数据库”要求的大部分目的,但它可能是一个解决方案。

答案 2 :(得分:1)

关键是要找到一种方法来存储cookie中的一条信息和数据库中的一条信息,这些信息一起获得明文密码,但是单独是没用的。

我能想到的最好的方法是创建一个类似于@fire建议的随机令牌:

$token = md5(uniqid(mt_rand(), true));`

然后使用此令牌加密密码并将加密的密码存储在包含userid的cookie中,以便您知道此加密内容的用途。

当客户端返回时,cookie可用于通过id检索数据库行,您可以从数据库中提取令牌以解密cookie信息以获取明文密码。这样,如果有人攻击cookie,他们会获得加密密码;如果他们进入数据库,他们会获得解锁密码但没有加密密码的密钥。

答案 3 :(得分:1)

保持用户注册

使用简单的令牌系统,将令牌存储在用户数据库中并存储在cookie用户端。 如果您需要更多相关信息,我建议谷歌(这很简单)

对于纯文本密码

您可以使用多种方法将其存储在RAM中,这是一个带memcache的例子

$memcache->set($token, $password); 

然后,使用以下命令从RAM中检索信息:

$user_password = $memcache->get($_COOKIE['token']);

有几种解决方案可以使用PHP在ram中存储数据:MemcacheAPC (the user cache part)