【问题标题】:How to secure a connection string in memory after loading it from app.config in a Winforms application从 Winforms 应用程序中的 app.config 加载连接字符串后如何保护内存中的连接字符串
【发布时间】:2019-12-05 06:41:51
【问题描述】:

我有一个旧应用程序,它使用 SQL Server 身份验证连接字符串连接到本地或基于 Intranet 的 SQL Server 实例。它目前使用 System.Configuration.ConfigurationManager 从 app.config 文件中获取连接字符串。但是,一旦从 app.config 文件中读取该连接字符串,它的值就会被加载到内存中,并且可以使用 Process Hacker 等工具公开以查看应用程序内存。我目前有一个带有方法的模块,该方法返回存储在 SecureString 对象中的连接字符串的值。连接字符串值在创建 ConnectionStringSection 对象时加载到内存中。 app.config 连接字符串 xml 通过 microsoft 文档中给出的说明进行加密

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-strings-and-configuration-files

我了解使用集成安全性是最佳实践,在这种情况下,我们的连接必须使用 SQL Server 身份验证。有没有办法消除或最小化连接字符串在应用程序内存中的暴露?

Public Function GetConnectionString() As SecureString
    Dim fileMap As ExeConfigurationFileMap = New ExeConfigurationFileMap
    fileMap.ExeConfigFilename = Environment.CurrentDirectory + "\app.config"
    Dim config As Configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None)
    Dim section As ConnectionStringsSection = TryCast(config.GetSection("connectionStrings"), ConnectionStringsSection)

    Dim secureString As New SecureString

    For Each character As Char In section.ConnectionStrings("ConString").ConnectionString.ToCharArray
        secureString.AppendChar(character)
    Next

    Return secureString
End Function

memory dump after first call to get connection string

【问题讨论】:

  • 您使用哪个工具进行内存分析?
  • 查看连接字符串中的Persist Security Info 键。不确定,但它可能会对您有所帮助。
  • @dotnetstep processhacker.sourceforge.io 运行它,找到你的进程 -> 属性 -> 内存选项卡 -> 字符串按钮和创建 ConnectionStringsSection 对象后存储在程序内存中的连接字符串数据。跨度>

标签: .net vb.net connection-string password-protection configurationmanager


【解决方案1】:

这是我用来以纯文本形式保存密码的工作流程。

1) 使用对称加密对连接字符串本身中的密码进行加密,以便通过调用将其加载到内存中时

Dim section As ConnectionStringsSection = TryCast(config.GetSection("connectionStrings"), ConnectionStringsSection)

公开的值是加密值,而不是纯文本。

https://docs.microsoft.com/en-us/dotnet/standard/security/encrypting-data

2) 解密密码并将其每次一个字符附加到 SecureString 对象以进行存储。

https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netframework-4.8

Public Shared Function DecryptString(ByVal srcString As String) As SecureString

        Dim p As Byte() = Convert.FromBase64String(srcString)
        Dim rv As RijndaelManaged = New RijndaelManaged
        Dim ms As MemoryStream = New MemoryStream(p)
        Dim cs As CryptoStream = New CryptoStream(ms, rv.CreateDecryptor(keyb, ivb), CryptoStreamMode.Read)
        Dim secureString As New SecureString
        Try
            Do
                Dim character As Integer = cs.ReadByte()
                If character = -1 Then
                    Exit Do
                End If
                secureString.AppendChar(Chr(character))
            Loop
        Finally
            ms.Close()
            ms.Dispose()
            cs.Close()
            cs.Dispose()
        End Try
        secureString.MakeReadOnly()
        Return secureString
    End Function

3) 使用 SecureString 对象和用户名构造一个 SqlCredential 对象,其中“GetUserName()”从连接字符串中获取用户名,“GetPassword()”获取 SecureString 密码

https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcredential.-ctor?view=netframework-4.8

Dim SqlCredential = New SqlCredential(GetUserName(), GetPassword())

4) 从这里您可以使用仅包含“Initial Catalog=;Data Source=;”的连接字符串构造 SQLConnection 对象连接字符串和 SQLCredential 对象的一部分。 "GetConnectionString()" 将返回上述连接字符串。

https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.-ctor?view=netframework-4.8#System_Data_SqlClient_SqlConnection__ctor_System_String_System_Data_SqlClient_SqlCredential_

Dim connection = New SqlConnection(GetConnectionString(), SqlCredential)

5) 如果您使用的是实体框架并且需要将该连接传递给您的 DBContext 对象,您可以使用此构造函数。

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/connection-management

Dim myDbContext = New DBContext(New SqlConnection(ConnectionString, SqlCredential))

【讨论】:

    猜你喜欢
    • 2011-05-19
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 2011-02-18
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多