Web 应用程序加密密钥管理

信息安全 Web应用程序 加密 密钥管理
2021-08-11 15:21:15

简而言之,让我们考虑一个 Web 应用程序,它将一些信息作为加密数据存储在数据库中。虽然我故意试图保持这种通用性,但这里有一些假设:

  • 加密数据仅存储在数据库中(不在其他地方)。给定记录中的某些字段是加密的,有些则不是。
  • Web 应用程序必须将加密数据写入数据库。
  • Web 应用程序必须能够读取和显示加密数据。数据仅显示在应用程序的身份验证和授权管理部分。
  • 数据是需要保护的敏感信息,以防数据被暴露/访问(没有密钥*)。

问题:

  • 您在哪里/如何存储用于加密的密钥?首先,在Web服务器和数据库服务器相同的系统中,如何管理密钥?其次,在 Web 服务器和 DB 服务器分开的系统中,如何管理密钥?
  • 密钥只是受权限限制的文件吗?存储在一些单独的工具/软件中?我已经看到有人提到有时加密密钥也被加密,但不清楚在哪里可能会有所帮助。

我知道这是一个相当基本的安全问题,所以如果有我可能缺少的资源,那也会非常非常有帮助。我花了很多时间(多年来)试图根据有关 Web 应用程序安全性(OWASP、PCI DSS 等)的信息来掌握这些信息,但很多时候这些信息是非常通用的(例如,“保护数据”、“加密数据”)或非常具体的(“用 AES 加密某些东西……”)。

* 我了解这本身并不是一个完整的安全解决方案。我知道有几个向量可以获取这些信息并对其进行解码。我承认这可能是一个糟糕的问题:)

编辑以添加有关此问题假设的更多信息

2个回答

虽然在之前的答案中提供了一些很好的信息,但存在一个关键的设计缺陷,并没有真正注意到 - 但来自问题中的一些隐含假设。

区别不应该是:

  • Web 应用程序和数据库在同一台服务器上
  • 不同服务器上的 Web 应用程序和数据库
  • 应用程序与数据库加密

设计应该从:

  • 谁需要访问加密/解密密钥?

或者,实际上更正确:

  • 谁负责保护数据的机密性?

反过来,这来自:

  • 您要防范哪些威胁?
    或者
  • 您试图阻止谁读取您的数据?

只有基于这些问题,你才能设计出一个设计合理的密码系统。(并防止@DW 提到的加密仙尘)。

因此,一些示例场景:

  • 用户应负责加密,甚至阻止应用管理员看到数据
  • 客户端应用程序应该负责,而不必让用户参与 - 但这仍然需要在客户端完成(例如备份程序)。
  • 作为业务逻辑的一部分,appserver 应用性地和专门地加密选定的数据(即使 dba 也看不到数据)
  • 数据库服务器应自动且透明地加密存储的数据。(这只能防止数据库文件/物理磁盘被盗,但需要注意......)。

为简单起见,我们假设加密应该在服务器端完成,责任在服务器,最终用户(和管理员)对加密没有影响。

那么,主要问题是由应用程序服务器还是数据库服务器执行加密?(实际上没那么简单,还有其他选择……)
这与大多数安全问题一样,又回到​​了权衡:

  • 您会管理自己的密钥,还是更喜欢基础架构自动抽象它?(原来的问题......下面的更多信息......)
  • 您是否担心恶意(或不称职、缺乏经验)的程序员?
  • 您是否担心恶意管理员?
  • 您是否担心未经授权的应用程序使用?
  • 您是否担心未经授权的 SQL 访问?
  • 您是否担心未经授权的直接文件访问?
  • 您是否担心物理磁盘/服务器被盗?

等等。(注意,上面的一些问题是无关紧要的,不能通过服务器加密来解决)。


现在,假设您根据上述内容在应用服务器加密和数据库加密之间做出了决定。
请注意,Web 服务器和数据库是否在同一台服务器上,在这里几乎没有影响 - 如果应用程序正在加密,那么它只是向数据库发送“特殊”数据,否则它没有实际意义。但是,这确实会影响上述威胁讨论 - 一些问题已被设计淘汰,一些问题得到了增强......

  • Web / 应用服务器加密
    • 用于加密数据的加密密钥 (EK) 本身应由密钥加密密钥(KEK) 加密。
    • 加密的 EK 应该存储在一个受保护的地方 - 这可以是一个文件、一个注册表项,无论什么 - 重要的是限制对它的访问,仅限于应用服务器的用户(也许是管理员 - 见下文)。
    • KEK 也需要保护——这有点棘手。
      如果您使用的是 Windows,则可以轻松访问DPAPI - 它提供操作系统级别的密钥管理,因此您可以让操作系统加密您的 KEK 并透明地为您管理密钥。(在幕后,DPAPI 最终依赖于知道用户的密码(在 USER_MODE 中),因此这是实际已知秘密的最后一个弱点 - 但其他人不应该首先知道服务器的密码,对吧?)
      另一种选择是外部设备/HSM,下面将进一步讨论。
    • 当然,KEK 还需要访问控制——限制性 ACL 等等。
    • 您想要将 EK 与 KEK 分开的原因有几个:您不想使用单个密钥加密大量数据;如果您需要更换密钥,它会变得容易得多(只需使用新的 KEK 重新加密 EK);您可以在 KEK 上使用更强、更慢、更复杂的加密/存储;如果您需要符合 PCI 标准,您可以在 KEK 上实现拆分知识;和更多。
    • EK 和 KEK 都不应长期未加密存储 - 取决于您的平台/语言,这意味着例如不要将其存储在 .NET 或 Java 中的 String 对象中。相反,将其存储在可变字节数组中,并始终确保尽快处理它。
    • 一些框架甚至更进一步,提供特定的受保护对象。例如,在 .NET 中,您可以使用System.Security.Cryptography.ProtectedMemory和/或System.Security.Cryptography.ProtectedData类来保护密钥,即使在内存中也是如此。
  • 数据库加密
    • 如果您让数据库服务器执行加密,这将变得容易得多:表/字段被配置为自动加密存储在其中的任何数据,密钥管理是完全透明的(来自应用程序的 PoV,而不是 DBA),并且很快。
    • 例如,Oracle 和 MS SQL Server 都支持自动内置加密。对于 MSSQL,密钥管理很复杂,但与我上面描述的类似。简化:有一个存储在数据库中的 EK,dba 可以将其配置为用于加密/解密表或字段。这是在一个受保护的表中,由 KEK 加密,然后由服务器级 KEK 加密,然后使用 MSSQL 服务帐户上的 DPAPI 加密。
    • 或者,MSSQL 还支持使用异步加密,例如存储公钥/私钥对——这在特定场景中很有用。
  • 第三种选择:外部加密存储,或HSM(硬件安全模块)这可以是共享硬件设备、服务器或硬件卡或加密狗……等。
    • 这些设备旨在非常安全地保护少量数据 - 例如,您的 KEK。
      同样,将 EK 与 KEK 分开的另一个原因 - 这将使您能够使用 EK 有效地加密和解密大量数据,同时仍然安全地管理 KEK。
    • HSM 通常通过特殊的驱动程序或 API 访问,也可以将它们插入数据库加密(取决于产品等)。

您在哪里/如何存储用于加密的密钥?

标准方法如果您在 SQL 或 Oracle 数据库之类的东西上使用内置加密,数据库将生成一个加密密钥并使用另一个密钥保护密钥或主密钥对其进行加密。这可以是密码短语或存储在例如 .pem 文件中的较长密钥。

这通常存储在只有 root/Administrator 和数据库服务帐户可以访问的受限目录中。在数据库启动时,密钥被读取并加载到内存中。然后将其用于解密加密密钥。

首先,在Web服务器和数据库服务器相同的系统中,如何管理密钥?

密钥存储在服务器上的目录中。更新或撤销通常是通过数据库程序。

其次,在 Web 服务器和 DB 服务器分开的系统中,如何管理密钥?

密钥仅本地存储在数据库服务器上。更安全的选择是在任一情况下使用硬件安全模块 (HSM)。这是连接到服务器并用于存储密钥的硬件设备,而不是服务器上的受限文件夹。

密钥只是受权限限制的文件吗?存储在一些单独的工具/软件中?我已经看到有人提到有时加密密钥也被加密,但不清楚在哪里可能会有所帮助。

只要您管理管理员访问权限并监控未经授权的登录、作为服务帐户的登录、添加了对该文件夹的访问权限的新帐户或组,限制该文件夹是可以接受的。如上所述,如果您要保护的数据和您面临的威胁需要它,HSM 是更安全的选择。

通常,数据库将创建实例或表密钥,然后使用主密钥对其进行加密。进一步加密主密钥几乎没有好处。