【问题标题】:Protect PII in web app database by encrypting with public key paired with private key protected by users' own passwords?通过与受用户自己的密码保护的公钥配对的公钥加密来保护 Web 应用程序数据库中的 PII?
【发布时间】:2011-11-06 12:09:50
【问题描述】:

目标:

我希望允许用户在自定义 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. 由于加密,每个相对较小的数据位都会占用数据库中更多的空间。

我的问题:有更好的方法吗?

【问题讨论】:

  • 一旦您的服务器受到威胁,几乎不可能确保得到保护。只要有人可以访问 php 代码,他就可以轻松地修改代码以在登录时将所有密码(或密钥对)写入明文文件。一旦知道盐(或知道它是如何构造的),哈希就不会被保存以进行保护。
  • 是的,只要漏洞未被发现,就可以捕获密码。这个想法是遏制和最小化泄漏。至少一些数据仍会受到保护,因为希望能够很快发现违规行为,并且并非所有用户都会在该时间范围内登录。
  • 您到底想在 PHP 会话中存储什么?如果您只在登录时解密私钥,我不明白为什么您需要在内存中添加额外的加密密钥。
  • 需要将密码存储在 PHP 会话中,因为私钥将受到密码保护,并且每次从数据库中提取 PII 时都需要对其进行解密和使用。无需仅仅因为用户登录就提取所有 PII 并解密。用户只能查看在任何给定会话期间存储的 PII 的一小部分。

标签: mysql security encryption pii


【解决方案1】:

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

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

原图:

EBC模式(这是mysql的AES_ENCRYPT()使用的):

但如果数据库受到攻击,攻击者将通过启用query log 来击败AES_ENCRYPT()

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

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

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

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

防范法律威胁的最佳方式是由经验丰富的律师撰写强有力的条款和条件。

【讨论】:

  • +1 很好地展示了 EBC 的弱点以及有关法律威胁的建议。然而,我很确定 OP 不想使用 AES_ENCRYPT 及其对应项,因为他在帖子中说“如果托管帐户被盗,数据很容易被读取。”,他想通过使用来防止一种非对称加密/解密方案。
  • @Niklas 是的,他想使用非对称加密,这在所有方面都是一个更糟糕的主意。
【解决方案2】:

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

【讨论】:

  • 防止密码破解的更好方法是迭代哈希算法(如果您每秒只能检查 10 个密码,暴力攻击将不可行),尤其是对您的用户强制执行严格的密码策略(最少长度,需要特殊的字符/数字/大写/小写)。不要小看现代 GPU 破解器的威力,它每秒可以轻松检查数亿个弱散列密码(当时这只是一张显卡)。
  • 是的,严格的密码策略有很大帮助。没有它,那么即使是每秒 10 个密码也可能足够快以发现高频密码。几年前,我是一个系统的系统管理员,所有密码都以明文形式存储,我肯定看到各种密码不断出现(已知用户是唯一的):“密码”、“p@ssword”、“橙色” , "ilove[some_name]", "f*ckyou" 和变体, "flower", 1337 个版本的常用词等。不过,关键拉伸也有帮助。
猜你喜欢
  • 2010-09-26
  • 2019-11-11
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 2011-04-15
  • 2012-01-29
  • 2019-07-14
  • 2013-03-26
相关资源
最近更新 更多