具有多个 Web 应用程序的 .NET6 中的数据保护

Data Protection in .NET6 with multiple web applications

我有 2 个负载平衡的 IIS 服务器 - 镜像。 每个服务器都有多个 .NetFramework Web 应用程序。 每个应用程序 运行 在不同的池用户下,代码放在不同的文件夹中。

现在我需要将这些应用程序迁移到 .NET6

我有 dp.Keys table 的 MSSQL 数据库。 我遇到了 DataProtection 的问题——所有应用程序都使用相同的密钥。 因此我不能使用 DpapiNG 密钥保护。我还希望每个应用程序有 1 个密钥(第一台服务器上的 app1 和第二台服务器上的 app1 使用数据库中的 key1)。

这是我的代码:

services
   .AddDataProtection()
   .SetApplicationName("App1")
   .AddKeyManagementOptions(options => options.XmlRepository = new SqlServerXmlRepository(connectionString, "dp", "Keys"));

我进行了一些挖掘,发现 DefaultKeyResolver(由 AddDataProtection() 使用)采用 FirstOrDefault() 密钥。它不会为这个特定的应用程序寻找密钥。

var preferredDefaultKey = (from key in allKeys
     where key.ActivationDate <= now + _maxServerToServerClockSkew
     orderby key.ActivationDate descending, key.KeyId ascending
     select key).FirstOrDefault();

这是预期的行为吗?对所有应用使用 1 个密钥是否安全? 看起来只有证书才能保护密钥?

在这里找到答案:https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-6.0

数据保护和应用隔离

  • 当多个应用程序指向同一个密钥存储库时,目的是让这些应用程序共享同一个主密钥material。数据保护是在假设共享密钥环的所有应用程序都可以访问该密钥环中的所有项目的假设下开发的。应用程序唯一标识符用于隔离从密钥环提供的密钥导出的应用程序特定密钥。它不期望项目级别的权限,例如 Azure KeyVault 提供的权限,用于强制执行额外的隔离。尝试项目级权限会产生应用程序错误。如果您不想依赖 built-in 应用程序隔离,则应使用单独的密钥存储位置,而不是在应用程序之间共享。
  • 应用程序鉴别器用于允许不同的应用程序共享相同的主密钥material,但保持它们的加密有效负载彼此不同。对于能够读取彼此的加密负载的应用程序,它们必须具有相同的应用程序鉴别器。
  • 如果应用程序遭到破坏(例如,通过 RCE 攻击),则该应用程序可访问的所有主密钥 material 也必须被视为已被破坏,无论其 protection-at-rest 状态如何。这意味着如果两个应用程序指向同一个存储库,即使它们使用不同的应用程序鉴别器,其中一个的妥协在功能上等同于两个的妥协。即使两个应用程序使用不同的静态密钥保护机制,这个“功能上等同于两者的妥协”条款仍然成立。通常,这不是预期的配置。 protection-at-rest 机制旨在在对手获得对存储库的读取权限的情况下提供保护。获得存储库写入权限的对手(可能是因为他们获得了应用程序内的代码执行权限)可以将恶意密钥插入存储。数据保护系统有意不针对获得密钥存储库写入权限的对手提供保护。
  • 如果应用程序需要真正相互隔离,它们应该使用不同的密钥存储库。这自然不符合“隔离”的定义。如果应用程序都对彼此的数据存储具有读写访问权限,则应用程序不会孤立。

我决定使用具有 DpapiNG 保护的 Azure blob 存储(每个应用程序一个容器)。效果很好。

new BlobContainerClient(connectionString, containerName).CreateIfNotExists();            
services
    .AddDataProtection()
    .PersistKeysToAzureBlobStorage(connectionString, containerName, "encryptedKey.xml")
    .ProtectKeysWithDpapiNG();