【问题标题】:Where to store db passwords when using Windows .NET or ASP.NET applications使用 Windows .NET 或 ASP.NET 应用程序时存储数据库密码的位置
【发布时间】:2012-03-25 11:23:12
【问题描述】:

我有一个困扰我多年的场景。如果您必须使用用户名和密码连接到数据库或其他服务(如 Web 服务),那么如果您通过 .NET 程序集进行连接,那么在哪里存储这些信息最安全?我知道您必须对密码进行加密,但是您遇到了一种先有鸡还是先有蛋的问题——很好——您可以加密它,但是您将密钥放在哪里?

在 .NET 中,您不能对密码进行硬编码,因为您可以反编译 .NET 代码。

我研究过在隔离存储中使用基于程序集的权限,但 MS 建议不要在其中存储未加密的秘密项目,因为特权用户可以获得访问权限,所以我们再次将问题从 A 点转移到 B 点。例如,无需了解数据库中信息的域管理员将能够获得访问权限,因为能够成为域中任何工作站的管理员。

您可以加密应用程序。 Config 和 Web.Config,但我相信特权用户可以访问密钥。

我认为您在使用 DPAPI 时遇到了同样的问题。

我曾考虑将密码存储在远程数据库中,并在远程数据库中进行加密,并通过操作系统身份验证来获取它们,但我们部门禁止将密码存储在数据库服务器上。我很确定我被卡住了,需要确认。

【问题讨论】:

  • 我知道这是不久前的事了,但我已经回答了您的问题如何存储加密的密码。请看一看。

标签: c# asp.net vb.net password-protection password-storage


【解决方案1】:

****已针对 Windows 10 1903+ 更新 ****

Microsoft has removed the dlls used by the previous method from WinMetadata,即使在进行旧操作时,它们现在也不可用。相反,they now either propose to use a Target Framework Moniker or a Nuget package 称为 Microsoft.Windows.SDK.Contracts,它公开了现代 Windows API。 [官方细节可以在这里找到]。 请注意,要正确安装 nuget,必须将数据包管理设置为 PackageReference 而不是 Packages.config,否则即使它看起来像已安装,但它不起作用。

如果尚未设置此管理器,通常可以通过右键单击 packages.config 文件并选择 @987654328 将 packages.config 文件转换为新格式(集成在项目文件中) @。 如果 Packages.config 文件尚不存在,则可以通过进入 Nuget 选项将默认设置为使用 PackageReference。请注意,默认设置在 .Net FW、.Net Std 和 .Net Core 之间有所不同。 当我个人不得不这样做时,奇怪的是,它不想迁移文件。我必须完全卸载我的包,删除文件,设置默认值并重新安装包。如果我没记错的话,和 TFVC 有关。

API 应该会再次可用。

**** 原帖 ****

如果您使用的是仅 Windows 8+ 解决方案,您还可以使用 Windows 密码保险箱。 最初,它是为 Metro Apps 构建的,但也支持 Winform 和 WPF 应用程序。

基本上,你需要的是

  1. 在第一个属性组内的项目文件中添加以下行
    <TargetPlatformVersion>8.0</TargetPlatformVersion>

  2. 参考Windows.Security

    • 打开参考管理器窗口
    • 选择Windows标签
    • 选择Core子标签
    • 检查Windows.Security
  3. 在代码中,使用(这是vb但C#是等效的)

    Dim vault = New Windows.Security.Credentials.PasswordVault()
    vault.Add(New Windows.Security.Credentials.PasswordCredential(resource, userName, password))
    Dim cred = vault.Retrieve(resource, logon)
    cred.RetrievePassword()
    Dim pwd = cred.Password
    

参考:

  1. https://docs.microsoft.com/fr-ca/archive/blogs/cdndevs/using-windows-8-winrt-apis-in-net-desktop-applications
  2. https://docs.microsoft.com/en-us/uwp/api/Windows.Security.Credentials.PasswordVault?view=winrt-19041

【讨论】:

    【解决方案2】:

    您可以使用 .NET Framework 的以下方法来保护您的数据;他们在内部使用 DPAPI 来保护您的数据,您可以直接在 C# 或 VB.NET 中使用它们,而无需摆弄系统 DLL 调用:

    namespace System.Security.Cryptography
    {
        // Summary:
        //     Provides methods for protecting and unprotecting data. This class cannot
        //     be inherited.
        public sealed class ProtectedData
        {
            public static byte[] Protect(byte[] userData, 
                byte[] optionalEntropy, DataProtectionScope scope);
            public static byte[] Unprotect(byte[] encryptedData, 
                byte[] optionalEntropy, DataProtectionScope scope);
        }
    }
    

    要使用它,请将引用 System.Security 添加到您的项目中。我强烈建议使用字节数组 optionalEntropySALT 添加到您的受保护数据中(向字节数组添加一些随机值,这些值对于您要保护的数据是唯一的)。 p>

    对于scope,您可以使用DataProtectionScope.CurrentUser,它将加密数据以使用当前用户的凭据进行保护。

    在某些情况下,DataProtectionScope.LocalMachine 也很有用。在这种情况下,受保护的数据与机器上下文相关联。使用此设置,计算机上运行的任何进程都可以取消数据保护。它通常用于在不允许不受信任的用户访问的服务器上运行的特定于服务器的应用程序。

    使用Protect方法加密数据,使用Unprotect解密。您可以根据应用程序的要求(文件、数据库、注册表等)存储返回的字节数组。

    有关这些方法的更多信息,请访问 MSDN:

    对于代码示例,如果您对加密应用程序的 .config 文件的某些部分感兴趣,请查看:

    我建议您使用SALT(通过使用optionalEntropy 参数) - 它可以防止彩虹表攻击。


    我想提一下 DPAPI 解决方案的一个缺点:密钥是根据您的 Windows 凭据生成的,这意味着有权访问您的 Windows 凭据的任何人都可能访问受保护的数据。在您的帐户下运行的程序也可以访问受保护的数据。

    【讨论】:

      【解决方案3】:

      这是个好问题,我自己一直在寻找答案。我遇到的问题是确保数据库密码的安全,以防服务器被黑客入侵并且可以检索单个文件。我发现的一个非常有趣的选项是 web.config 的部分可以通过 .NET 框架自动加密和解密,该框架将使用 Windows 安全存储为您保存和检索加密密钥。在我的情况下,因为我的托管服务提供商不支持它,所以它不可用,但你可以看看这个选项。我认为它可能起作用的原因是,您可以独立管理用户可能访问 Windows 安全商店的安全性,并显着限制任何潜在的违规行为。闯入服务器的黑客可能会获得您的配置文件和所有程序集的副本,但访问解密密钥将是他的另一个障碍。

      【讨论】:

        【解决方案4】:

        您不想将密码存储在程序集中,而重新发明轮子只会带来比其价值更多的麻烦(并引入更多漏洞)。如果您在数据库和 Web 服务器上都使用 MS 平台,那么处理此问题的最简单方法是 use a trusted connection,并将 SQL 服务器上的权限授予您的应用程序正在使用的身份。

        其次,我只想let DPAPI do its job to encrypt your connection settings

        【讨论】:

        • 我遇到的主要问题是我正在使用的 Web 和 Windows 应用程序都在我无法使用操作系统身份验证的情况下运行。特别是 Windows 应用程序位于多用户框上——据我从文档中得知,如果我在用户模式下使用 DPAPI,我将不得不为每个用户配置单独的设置。如果我在机器模式下使用 DPAPI,我的连接信息将对所有使用 DPAPI 的应用程序可用。不幸的是,我还必须使用符合 FIPS 140 标准的提供程序,我认为它排除了 DPAPI 和 RSA。我认为最好的方法是从盒子里取出密码。
        • 哎呀。 DPAPI 使用 TripleDES,我相信它是 FIPS。这在多用户访问领域仍然没有帮助,在机器模式下,所有使用 DPAPI(据我了解)的应用程序都可以访问相同的信息
        • 可以使用用户存储 DPAPI 加密配置部分。我已经用带有说明的链接更新了我的答案。请注意,这些说明缺少有关配置应用程序池(如果使用 IIS7+)以加载身份的用户配置文件的任何指导。我认为您需要打开该标志,因为 DPAPI 用户存储需要加载配置文件。
        • 问题是,如果您将密码从盒子中移出,您仍然需要保护密码才能获取密码。此外,这使得获取凭证的基础设施更加复杂,并引入了一些脆弱性。我很好奇关于用户存储 DPAPI 的问题。听起来您真的可以在应用程序中使用 x509 或身份管理!
        【解决方案5】:

        这里有几个选项。

        1. 将它们存储在加密的配置文件中
        2. 将它们存储在使用生成的种子加密的外部文件中。混淆存储此基本种子的代码或将其存储在 c++ dll 中(难以反编译)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-09
          • 2015-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多