7

目标:

我希望允许用户在自定义 Web 应用程序(支持托管环境中的 PHP/MySQL)中创建问题并从其他用户那里收集信息,并保护收集到的数据。

背景:

所有用户回答的默认问题都足够笼统,不能将其解释为个人身份信息 (PII),从而限制了我保护它的责任,但创建自己问题的用户可能会要求 PII,这将成为一种责任。

我想做的是以这样一种方式保护这些信息,即如果主机帐户或数据库遭到破坏(或两者兼有!),如果没有大量工作,PII 将无法恢复,即使那样,也只有一个一小部分理论上是可以收回的。

建议的解决方案:

假设 MySQL 的内置AES_ENCRYPT()/AES_DECRYPT()函数用于加密 PII 表,则需要将密码存储在主机帐户中,因此如果主机帐户被盗,数据很容易被读取。

由于用户的密码受到很好的保护(用盐散列),我正在考虑在身份验证期间捕获他们的明文密码,对其进行加密,并将其存储在 PHP 会话中,直到用户注销。

将为每个用户创建一个公钥/私钥组合,私钥受用户密码 + salt 的密码保护。

然后,当基于该用户的自定义问题的 PII 数据添加到数据库时,用户的公钥将用于加密他们通过应用程序收集的 PII。当读取数据时(仅当用户登录时),数据将使用用户的私钥(使用密码+盐解锁)解密。

我看到的好处是:

  1. 在最坏的情况下,服务器完全受损,读取应用程序代码以查找加密密钥,解密 PHP 会话文件以查找用户密码,然后解密与该用户关联的 PII 表中的条目,然后仅从问题中收集 PII可以恢复当前登录的用户。任何未登录的用户都是安全的。
  2. 即使是 DBA 或类似人员也无法读取 PII。

我看到的缺点是:

  1. 用户密码在登录时以可恢复的形式存储。
  2. 忘记密码的用户将失去对其数据的访问权限。
  3. 由于加密,每个相对较小的数据位都会占用数据库中更多的空间。

我的问题:有没有更好的方法来做到这一点?

4

2 回答 2

7

从安全角度来看,我发现这种设计存在许多问题。首先,密码绝不能加密,这是CWE-257识别的漏洞。

AES_ENCRYPT()此外,由于不止一个原因,更多的 MySQL完全是垃圾。它使用 EBC 模式,这是一个很好的例子,说明为什么这是废话:

原图:

在此处输入图像描述

EBC 模式(这是 mysqlAES_ENCRYPT()使用的):

在此处输入图像描述

但是,如果数据库受到攻击,攻击者将AES_ENCRYPT()通过启用查询日志来击败。

应避免使用用户密码进行加密,您应该使用密码随机数。如果您确实使用密码,请确保您使用 String2Key 功能。您还必须使用带有随机 iv的 CBC 或 CMAC 模式。我真的不明白非对称密码学有什么帮助。非对称密码学非常慢,内存密集。当攻击者控制消息时,它保护的数据会变得不那么安全,因为您可以比较密文消息。这就是为什么随机 IV很重要,而在非对称世界中,您没有这种级别的保护。

密钥生成应该类似于: $key=string2key($base_nonce.$salt.$user_password)

确保您的 string2key 函数的输出与您的键空间大小相同。所以 aes 128 需要一个 128 位的密钥。每个密码都应该有自己的$salt,并且$base是存储在文本文件中的加密随机数。(攻击者必须在破解密钥之前读取这个文件,如果这个值像 128 位一样大,那么它就是一个有争议的点。)每条消息都需要自己的$iv,这个值也必须是一个加密随机数(类似于盐)。我会生成$salt,$iv$base_nonce. /dev/urandomIV 可以与密文一起以纯文本形式存储在数据库的列中。

从法律的角度来看,即使您构建了一个安全的密码系统,您仍然会遇到内部威胁的问题,如果服务器完全受到威胁,所有数据仍然会受到威胁。这真的不是工程问题。

对法律威胁的最佳防御是由熟练的律师编写的强有力的条款和条件。

于 2011-09-01T15:55:13.370 回答
0

我会担心的一个问题如下。“任何未登录的用户都是安全的”部分过于乐观。通过使用用户密码保护私钥,您将自己暴露在各种密码暴力攻击中。不仅适用于当前会话,而且适用于所有会话。一种有效的方法是简单地列举前 100 个常用密码,例如,对所有用户进行尝试。攻击者必然会发现一些密钥。(我假设您将每个用户的随机盐存储在攻击者可以看到的用户记录中,或者您拥有攻击者能够通过妥协获得的秘密盐。)

于 2011-09-01T13:37:20.033 回答