我正在开发一个存储敏感用户数据的网络应用程序。尽管数据很敏感,但我们希望将其永久存储,因为用户可能希望稍后返回并重新使用它。在用户会话期间,服务器必须可以访问用户数据。
我们可以假设与永久存储的数据集数量相比,活动会话的数量较低。
- 资产:存储在数据库中的部分数据非常敏感 - 但需要在用户会话期间在服务器端进行处理(这是应用程序的重点)并永久存储在那里(出于可用性原因)。
- 场景:黑客获得了对数据库的访问权限,并能够读取其中的所有数据。
注意:这并不意味着替代风险分析或安全管理的任何其他部分,也不意味着替代某些其他措施(密码策略、SSL/TLS、审计......你可以说它)。这是关于检查一项特定的安全措施。
建议的对策:用户数据加密
为了降低将所有敏感数据泄露给获得数据库访问权限的攻击者的风险,我想加密数据(与此问题中的选项 1 非常相似):
- 在用户注册期间,服务器会生成一个用户密钥
U
(AES)。 - 用户密钥使用密码派生密钥 (SHA256) 加密
d(p)
并存储在数据库中AES(d(p), U)
。 - 每次用户登录时,密钥都会被解密并存储在服务器端会话存储
p -> d(p) + AES(d(p), U) -> U
中。 - 只要会话持续,用户就可以使用他/她的数据。数据使用随机 AES 密钥(消息密钥
m
)加密。然后使用用户密钥对 AES 密钥进行加密,并与加密数据一起存储 (AES(U, m) + AES(m, data)
)。
问题1:该方案是否存在明显的安全漏洞(攻击者可以访问所有登录用户的数据除外)?
找回密码
上述方案的一个明显缺陷是没有进行密码恢复的过程:一旦密码丢失,用户密钥就无法解密,因此数据也丢失了。
为了解决这个问题,我们生成另一个 RSA 密钥对 ( M_pub + M_sec
)。公钥是应用程序配置的一部分。除了之前的方案:
- a) 用户密钥和用户电子邮件使用主密钥加密,并与用户记录一起作为恢复信息存储
RSA(M_pub, U+user.email)
我们在另一台服务器上有另一个应用程序,它可以访问私有主密钥(但不能访问数据库)。密码恢复将如下所示:
- 用户像往常一样开始密码恢复(重置密码-> 带有表单链接的电子邮件)。
- 用户选择一个新密码
p'
。 - 原始应用程序现在要求密码重置应用程序通过将恢复信息
RSA(M_pub, U+user.email)
和新密码派生密钥d(p')
发送到恢复服务器来解密用户密钥。 - 密码重置应用程序解密恢复信息
M_sec + RSA(M_pub, U+user.email) -> U + user.email
,发送通知电子邮件给user.email
(告诉用户如果他/她没有导致恢复,则报告事件)并将新加密的用户密钥发送AES(d(p'), U)
回原始应用程序。
恢复过程将受到速率限制,因此在发现泄露之前,泄露密钥的数量受到限制。
优点:
- 密码恢复仍然是即时的。
- 攻击者需要破解两个系统才能访问完整的数据库。
缺点:
- 能够访问一个系统的攻击者也可能获得对密码重置系统的访问权限。
问题2:这种密码恢复方式在多大程度上降低了加密的效果?(还值得做吗?)
问题 3:是否有任何其他流程可以提高数据安全性(如果服务器被黑客入侵)而不使自动密码恢复成为不可能?