c# - 配置文件篡改检测

标签 c# configuration

我希望能够检测到何时更改了关键配置文件。

我已经使用 Configuration Section Designer 创建了一个简单的配置文件,但现在我找不到一种简单的方法来加密结果或向其添加值以检查它是否已更改。

我希望能够防止未经授权的用户更改配置文件,或者至少知道文件是否已更改。

最佳答案

如果授权用户可以更改配置文件,高级方法是使用非对称 key 对文件进行签名。只有有权访问私钥的授权个人才能生成散列,但应用程序可以仅使用公钥来验证散列(以及文件本身)的合法性。下面是一种快速实现。

此实现需要生成三个文件:

  • 要签名的配置文件。
  • 包含配置文件哈希的应用程序可访问的文件。
  • 包含私钥参数的私有(private)配置文件。

  • 文件 (1) 和 (2) 由应用程序访问。文件 (3) 是 secret 的,仅限授权用户使用。

    基 native 制是这样的:
  • 生成RSA key 对,并保存公私钥信息。私钥信息保存在文件(3)中,公钥信息并入应用程序。此步骤仅执行一次。
  • 每当更改配置文件时,文件 (3) 用于签署文件的 SHA1 哈希。散列被保存到文件 (2) 中。
  • 每当程序加载配置文件时,它都会生成配置文件哈希,并使用公钥来验证签名。如果签名匹配,则继续;如果它们不匹配,则抛出异常。

  • 1. 生成 RSA key 对

    RSA key 数据可以生成为 XML:
    (use System.Security.Cryptography)
    
    var csp = new RSACryptoServiceProvider();
    string publicXml = csp.ToXmlString(false);
    string privateXml = csp.ToXmlString(true);
    

    这将生成以下格式的 XML 数据。
     publicXML:
     <RSAKeyValue>
        <Modulus>oQKZR9hHrqm1tauCFYpbFlwyRNIHeyc2HCX+5htF/oc1x8Nk8i+itTzwRlgQG1cICO6lX
             A+J9/OO2x2b9JILtk2tQow10xJdIsuiBeRwe7wJRdS8+l21F/JPY0eu/xiKQy
             ukzEWLjIxGX7UXb9e4ltIxyRUUhk5G/ia1trcxfBc=
        </Modulus>
        <Exponent>AQAB</Exponent>
     </RSAKeyValue>
    
     privateXml:
     <RSAKeyValue><Modulus>oQKZR9hHrqm1tauCFYpbFlwyRNIHeyc2HCX+5htF/oc1x8Nk8
    i+itTzwRlgQG1cICO6lXA+J9/OO2x2b9JILtk2tQow10xJdIsuiBeRwe7wJRdS8+l21F/JPY0eu/xiKQ
    yukzEWLjIxGX7UXb9e4ltIxyRUUhk5G/ia1trcxfBc=</Modulus><Exponent>AQAB</Exponent>
    <P>zpFEWa7ave3wHL7pw7pSG0KXDPRwhCzU1Z5/fLoqSrPQzbkRqU+cwDVO/6IId3HdeXE09kVIu9/HBId
    vupnY9w==</P><Q>x4pmqkmB7i8g9d3G6RSeZWYde8VOS5/OHUKgM6VrlQhgyrATpxGWAzJAe5eNO2BU
    axNO8fZPe+lUSCJgY6TN4Q==</Q><DP>jaNL05ayhDLHRl6dmUiDjg+N1SMyl17KHSON1O8tmoVLchQp
    CQf+ukiTP3NSDNy1eNTn9MkzAyeAphlbwf5Fpw==</DP><DQ>HhmUjw9zmBhn4m7H+JTxp94ViHwk6Wd
    70hIg1GmZpuuSnkCdVlBizqyf6YTc+x323ggVmo5LQyfZXOBCpgVQQQ==</DQ><InverseQ>iO0CKRGB
    2ULS6is/SwonqJw5fBsI9HTzx8rmKGA189dwlLGJSJuQo8uWmrLYhuo22BAqd0lMqxlKCHv6leeGPw==
    </InverseQ><D>RSLliJkRJqnO0cRkZjVzqWVLXIvHFJWgwXN7QXlik8mhSTbYqLnVpvcUwU/dErBLTf
    KTZLVza9nUdLgBGIKBrkbIqIWixq1fQ3zsEkyB/FQxwhIerTrhHyPzR+i3+5mduqQ7EBTj64u6STUf0y
    TXHW2FYlfAinNz+K3iQFFarEE=</D></RSAKeyValue>
    

    私钥字符串应(通过任何机制)保存到文件 (3)(私钥)。确认文件完整性的应用程序将需要公钥字符串(稍后在步骤 3 中讨论)。

    2. 签署配置文件

    要签署配置文件,您将需要在步骤 (1) 中生成的私钥 Xml 字符串。
        private byte[] GetFileSha1Hash(string file)
        {
            using (var fs = new FileStream(
                file, FileMode.Open))
            {
                return new SHA1CryptoServiceProvider().ComputeHash(fs);
            }
        }
    
        static string GetConfigurationFileSignature(string configfile, string privateXml)
        {
            var p = new RSACryptoServiceProvider();
            p.FromXmlString(privateXml);
            byte[] signature = p.SignHash(GetFileSha1Hash(configfile),
                   CryptoConfig.MapNameToOID("SHA1"));
            return Convert.ToBase64String(signature)
        }
    

    调用 GetConfigurationFileSignature 将返回一个 base64 编码的字符串。将此字符串保存到文件 (2) 中,应用程序将在其中引用它。

    3. 检查配置文件完整性

    加载配置文件时,应用程序应根据数字签名检查配置文件签名。公钥应该存储在应用程序中而不是配置文件中——否则,攻击者可以简单地用他/她知道对应私钥对的公钥覆盖配置文件中的公钥。
        static bool VerifyConfigurationFileSignature(string fileName, string publicXml, string signature)
        {
            var p = new RSACryptoServiceProvider();
            p.FromXmlString(publicXml);
    
            return p.VerifyHash(
                 GetFileSha1Hash(fileName),
                 CryptoConfig.MapNameToOID("SHA1"),
                 Convert.FromBase64String(signature));
        }
    

    (注意:可以使用 AppDomain.CurrentDomain.SetupInformation.ConfigurationFile 获取当前配置文件的路径。)

    当应用程序加载时,它可以使用配置文件的路径、公钥 XML 数据和已知签名调用 VerifyConfigurationFileSignature。如果此方法返回false,则说明文件已被篡改;如果返回 true,则证明该文件是合法的。

    最后说明
  • 密码学仅确保生成的数字签名是使用私钥生成的。攻击者可能仍然能够覆盖应用程序的验证逻辑以读取恶意配置数据。
  • 对配置文件的任何更改(包括添加注释、空格等)都会导致哈希无效。 GetFileSha1Hash 的一个更专门的实现可能会在 XML 中搜索特定的键/值对并仅对这些数据进行签名,从而允许对配置文件进行其他修改。
  • 上面的 GetFileSha1Hash 实现不可能在 XML 文件中包含散列本身,因为更新文件中的散列本身会使先前的散列无效。 GetFileSha1Hash 的专门实现可以在生成配置文件哈希时忽略生成的哈希值,从而避免需要单独的配置文件。
  • 关于c# - 配置文件篡改检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8961618/

    相关文章:

    c# - 将 Jasper .jrxml 转换为 Microsoft .rdlc

    java - JRebel Tomcat + Websphere

    java - 如何在用户之间共享 Eclipse 项目首选项?

    c# - 在 ASP.NET 中获取登录用户的用户 ID

    c# - 关于此代码的最佳实践和编码约定的一些希望简单的问题

    c# - C# 5.0 中的可选泛型类型参数怎么样?

    c# - 如何读取子项 sitecore 中的父项值

    java - 在 application.conf 中包含的 conf 文件中使用 Play Server 的 ID

    ruby - GIt 部署 + 配置文件 + Heroku

    c++ - 模板配置参数 VS 包含文件