在服务器上安全地加密/解密appsettings.json文件

11
如何保护用于加密Web应用程序的appsettings.json中敏感数据的加密密钥?
我想要在Web应用程序的配置文件中保护敏感数据。
在ASP.NET MVC4应用程序中,我们是这样处理的:
1. 不直接将敏感数据(例如连接字符串中的密码)添加到web.config(或web.prod.config等)中,而是写入占位符变量。 2. 部署服务(Octopus)会从其安全存储中检索敏感数据并覆盖web.config中的变量。 3. 然后使用aspnet_regiis.exe加密web.config的敏感部分。
现在我们正在使用ASP.NET Core,我们遵循的过程有些不同:
1. appsettings.json包含敏感数据的占位符变量,类似于以前工作的web.config。 2. 部署过程像以前一样用安全存储替换占位符与敏感数据。 3. 我认为我需要制作自己的自定义工具来加密appsettings.json文件的部分内容,并且需要制作一个可以解密appsettings.json的自定义配置提供程序。
我的问题是如何保护用于(a)和(b)的加密密钥。旧方法利用服务器的机器密钥加密文件。
我试图缓解的威胁是某人可以访问服务器上的appsettings.json并从中读取敏感数据(例如数据库密码等)。
我还对缓解这一威胁和/或此方法在一般情况下存在的其他问题的替代方法感兴趣。

你是在Azure上运行吗?那有一种安全的方式来存储应用程序外部的秘密。 - Jim W says reinstate Monica
@JimW 不,我没有使用Azure。 - Ergwun
即使您不在Azure上运行,我仍然建议您使用Azure密钥保管库来存储您的机密信息。首先,它非常便宜(每10,000次操作约为0.0159美元),其次,它可以从任何地方访问,甚至是在Azure之外。您可以拥有一个内存缓存,这样只有在应用程序启动时(或者在缓存过期时)才会进行一次对密钥保管库的REST调用,从而避免了进一步的延迟。第三,这是Microsoft推荐的方法。 - ThePretendProgrammer
@ThePretendProgrammer,你的评论是目前为止最好的答案,但我认为它需要成为一个回答而不是一个评论才能获得赏金。 - Ergwun
4个回答

2

如果您不信任服务器 - 您就无法保护存储在该服务器内部的“秘密”。

解释:

无论您发明了什么“安全”(=不安全)方案 - 当应用程序启动时,它必须能够将“秘密”解密为某些“可用”形式。

这意味着所有“解密”所需的“密钥”(证书等)都必须存在于此服务器上,并且对于应用程序是可访问的(否则应用程序无法启动)。

这意味着一些坏人可以访问服务器和应用程序,也可以访问其中的所有“密钥”,并“解密”您的秘密。可能是通过复制文件,可能是通过反编译您的应用程序,可能是通过转储您的应用程序内存 - 但它可以做到。

没有绝对的保护。


2
是的,我理解你的想法,但我仍然认为将加密密钥存储在appsettings.json中值得,因为这个SO问题的接受答案中提到了所有的原因。例如,当攻击者只能部分访问服务器或配置文件时。在ASP.NET Core中,在这种情况下存储密钥的最佳/最实用方法是什么,以便使用机器密钥提供类似于aspnet_regiis的保护水平? - Ergwun
1
这不正确,深度安全非常重要,如果您的服务器已被攻击,不一定意味着攻击者也获得了以管理员身份执行命令的权限。 - Norcino
@Norcino,无需管理员访问权限。如果应用程序具有足够的权限来访问某些机密(否则它将无法工作),那么具有相同“低”访问权限的任何主体都可以访问相同的机密。这里的主要问题是谁是坏人,因为“appsettings.json”对于“普通”访问者是不可访问的。如果话题发起者想要保护自己的Web服务器管理员...那是不可能的。 - Dmitry
1
@Dmtry我同意你的观点,但这并不包括由于利用或错误配置而导致未经授权的用户获得了对网站文件夹的读取访问权限,从而允许其读取配置文件。 使用安全深度原则,您必须假设存在漏洞,并采取行动限制损害和信息披露。不能假设入侵者已成功冒充管理员。 - Norcino

2
看起来你对“方法”不感兴趣,而是对ASP.NET Core支持的推荐方法感兴趣。虽然其他答案中提到Azure KeyVault作为敏感信息的良好存储,但它并不是存储方式,而是实际存储。 ASP.NET Core支持可重写配置的概念。也就是说,可以在配置系统中注册多个配置提供程序,并且它们注册的顺序很重要。每个注册的提供程序都会覆盖先前提供程序的设置-当然,只有它有的设置才会被覆盖。 换句话说,如果您已经注册了标准的JSON配置提供程序,然后再假设一个数据库配置提供程序,那么这些提供程序都具有的设置将获取后定义的提供程序(即数据库提供程序)定义的值。 因此,在您的情况下,这是我建议做的:
1. 将所有默认配置提供程序注册为原样。 2. 在最后注册Azure Key Vault(或类似的基于秘密存储的提供程序)配置提供程序。 3. 使用证书身份验证与Key Vault进行身份验证并读取敏感设置。
虽然这不是与您当前流程的一对一映射,但它符合ASP.NET Core原则。
您可以在此处阅读有关ASP.NET配置的更多信息:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/index?tabs=basicconfiguration 在这里,您可以阅读有关Azure KeyVault配置提供程序的信息:https://learn.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?tabs=aspnetcore2x 如果基于证书的身份验证对您不可行,请考虑将用于连接到Azure Key Vault服务的ClientIdClientSecret存储在环境变量中,并使用适当的配置提供程序(AddEnvironmentVariables()扩展方法将完成此操作)来访问它们。
这种设置将非常安全。祝你好运!

1
我正在将评论转换为答案 :)
即使您没有在Azure上运行,我仍建议使用Azure Key Vault来存储您的机密。首先,它非常便宜(~ $ 0.0159 / 10,000次操作),其次它可以从任何地方访问,甚至在Azure之外。此外,Azure Key Vault中的机密可以进行版本控制,这是一个很好的功能,支持每个环境的多个版本的机密(仅适用于预生产环境,因为生产环境应该有自己的密钥库)。Key Vault NuGet包具有在.NET Core内检索和添加机密的操作。这里是文档链接。
您可以拥有一个内存缓存,因此只在应用程序启动时(或者当缓存过期时)才进行REST调用(或Key Vault包方法调用)到Key Vault,从而防止任何进一步的延迟。第三,这是Microsoft推荐的方法。
希望这有所帮助。

1
这并不能解决孤立系统无法访问外部资源或安全策略不允许使用云服务的问题。 - Norcino

1
如果未经授权的人获得了对服务器的访问权限,那么窃取机密信息 - 比如数据库连接字符串,只是问题的一小部分(@Dmitry's answer)。
由于您希望更好地控制机密数据或配置,因此略微偏离通常的基于appsettings.json的方法是可以接受的。
您可以使用服务器证书进行非对称加密来处理机密信息,将其存储在单独的文件中(它可以是另一个.json文件),然后在启动/每个Web请求时读取文件并解密机密信息。这样,机密信息几乎与服务器证书/私钥一样安全。
另一种选择是对机密信息进行对称加密,并在启动时将密码提供给Web应用程序以便它可以解密机密信息。当托管Web应用程序的进程重新启动时,您必须再次提供密码(您可以使用另一台机器定期提供密码等方式)。
另请参见ASP.NET Core中的数据保护数据保护示例
有时,长而晦涩的密码或对本来易于人类理解的密码进行简单的混淆就足够了。也就是说,只是防范窃听。比如说,坐在管理员旁边的人将无法读取并记忆一串看似随机的字符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接