在应用系统中,保护数据库连接字符串的安全性至关重要。.NET 提供了一种通过 DataProtectionConfigurationProvider 加密连接字符串的方法,以防止敏感数据泄露。然而,在内网信息收集阶段,攻击者只需在目标主机上运行aspnet_regiis.exe这个命令行工具即可完成解密,获取数据库连接的明文字符串。
0x01 详解aspnet_regiis
aspnet_regiis.exe 是一个命令行工具,用于配置和管理 .NET 应用程序在 IIS 中的注册和设置。该工具通常与 .NET 版本一起安装,用于执行各种与 ASP.NET 配置相关的任务,一般有如下几种使用场景。
1.1 注册和卸载.NET版本
使用 aspnet_regiis 工具将特定版本的 ASP.NET 注册到 IIS 上,确保 .NET 应用程序可以在该版本上运行,注册命令如下所示:
aspnet_regiis -i
这将安装 .NET 并将当前版本的 .NET 关联到 IIS 中的所有应用程序。反之,卸载在IIS中的注册,命令如下所示:
aspnet_regiis -u
1.2 列出当前安装的.NET版本
aspnet_regiis 还提供一些命令可以列出 IIS 中注册的 .NET 版本和相关的脚本映射,具体命令如下所示。
aspnet_regiis -lk
0x02 .NET加解密提供器
在 .NET 中,DataProtectionConfigurationProvider 和 RsaProtectedConfigurationProvider 这两种加解密提供程序,通常用于加密和解密配置文件中敏感信息(比如,web.config 和 app.config),主要保护数据库连接字符串、应用程序设置以及其他需要保护的敏感数据。
2.1 DataProtectionConfigurationProvider
DataProtectionConfigurationProvider 是 .NET Framework 2.0 引入的默认加密提供程序之一,主要用于在单台服务器上加密和解密配置文件数据。原理上使用 Windows Data Protection API (DPAPI) 进行加密,这意味着加密数据与操作系统的用户或机器密钥绑定。只有加密时使用的同一用户帐户或同一台机器才能解密数据。假设在 web.config 中有一个连接字符串如下所示。
<connectionStrings>
<add name="MyDb" connectionString="Data Source=myServer;Initial Catalog=myDb;User ID=myUser;Password=myPass;" providerName="System.Data.SqlClient" />
</connectionStrings>
使用aspnet_regiis.exe进行加密数据库连接字符串的命令如下所示。
aspnet_regiis -pef "connectionStrings" "C:\path\to\your\project" -prov "DataProtectionConfigurationProvider"
加密后,内容将被替换成如下所示。
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAnu1l5eTFekKy...</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
通过aspnet_regiis.exe进行解密连接字符串的命令如下所示。
aspnet_regiis -pdf "connectionStrings" "C:\path\to\your\project"
因此,这种加密方式适用于单台服务器环境下的配置文件保护,不适合在多个服务器之间共享加密的数据。密钥由 Windows 操作系统管理,不需要额外的密钥管理。
2.2 RsaProtectedConfigurationProvider
RsaProtectedConfigurationProvider 使用 RSA 加密算法来保护配置文件中的数据。该提供程序需要用户生成一个 RSA 密钥对,然后使用公共密钥加密数据,使用私钥解密数据。这种方式使得可以在多台服务器之间共享加密数据,只要这些服务器都可以访问同一个 RSA 私钥。使用 RSAProtectedConfigurationProvider类加解密web.config时,第1步需要生成RSA密钥容器,命令如下所示。
aspnet_regiis -pc "MyKeys" -exp
第2步将密钥容器导出到 XML 文件,命令如下所示。
aspnet_regiis -px "MyKeys" "C:\keys.xml" -pri
第3步在另一台服务器上导入密钥容器,命令如下所示。
aspnet_regiis -pi "MyKeys" "C:\keys.xml"
随后,使用aspnet_regiis.exe进行加密数据库连接字符串的命令如下所示
aspnet_regiis -pef "connectionStrings" "C:\path\to\your\project" -prov "RsaProtectedConfigurationProvider"
解密数据库连接字符串的命令如下所示。
aspnet_regiis -pdf "connectionStrings" "C:\path\to\your\project"
因此,两种加密方式的选择取决于应用程序的部署环境。如果应用程序部署在单台服务器上,且没有跨服务器的需求,那么 DataProtectionConfigurationProvider 是一个简单且有效的选择。如果应用程序需要在多台服务器之间共享加密数据,则 RsaProtectedConfigurationProvider 更为合适,具体可以参考下图所示。
0x03 编码实现
在某些内网收集信息的情况下,安全评估或者渗透工程师可能需要解密这些连接字符串,因此有必要将上述理论知识转换成工具,通过使用 Sharp4DecryptConnect这款工具,可以轻松解密这些字符串,从而获取明文连接字符串。该工具首先会将站点根目录下的 web.config 文件复制到一个新创建的 dotNetMatrix 目录中,以防止直接操作原始配置文件导致意外损坏,具体代码如下所示。
string webConfigPath = Path.Combine(exeDirectory, "web.config");
string targetDirectory = Path.Combine(exeDirectory, "dotNetMatrix");
string targetWebConfigPath = Path.Combine(targetDirectory, "web.config");
if (File.Exists(webConfigPath))
{
Directory.CreateDirectory(targetDirectory);
File.Copy(webConfigPath, targetWebConfigPath, true);
Console.WriteLine($"web.config 已复制到 {targetWebConfigPath}");
}
代码中,通过 File.Exists 判断 web.config 文件是否存在,然后创建 dotNetMatrix 目录,并将 web.config 文件复制到该目录下。随后,使用 ProcessStartInfo 配置解密命令行参数,并启动 aspnet_regiis.exe 进程执行解密操作。解密结果通过 ReadToEnd() 方法获取,并输出到控制台。具体代码如下所示。
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = aspnetRegiisPath,
Arguments = decryptCommand,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using (Process process = Process.Start(psi))
{
string result = process.StandardOutput.ReadToEnd();
Console.WriteLine(result);
process.WaitForExit();
}
最后,打开dotNetMatrix文件夹查看解密后的web.config内容,可以发现数据库连接字符串已经成功解密。如下图所示。
0x03 小结
综上,使用DataProtectionConfigurationProvider 和 RsaProtectedConfigurationProvider 两种加密器可以提高攻击者获取明文密码的难度,但在获取目标webshell权限后,通过自动化攻击就可以完成加密连接字符串的解密操作。