配置文件上的篡改检测

时间:2012-01-22 14:05:39

标签: c# configuration

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

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

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

2 个答案:

答案 0 :(得分:7)

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

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

  1. 您要签名的配置文件。
  2. 包含配置文件哈希的应用程序可访问的文件。
  3. 包含私钥参数的私有配置文件。
  4. 应用程序访问文件(1)和(2)。文件(3)是保密的,仅限授权用户使用。

    基本机制是:

    1. 生成RSA密钥对,并保存公钥和私钥信息。将私钥信息保存到文件(3)中,并将公钥信息合并到应用程序中。此步骤仅执行一次。
    2. 每当更改配置文件时,file(3)用于对文件的SHA1哈希进行签名。哈希值保存在文件(2)中。
    3. 每当程序加载配置文件时,它都会生成配置文件哈希,并使用公钥来验证签名。如果签名匹配,则继续;如果它们不匹配,则抛出异常。
    4. <强> 1。生成RSA密钥对

      RSA密钥数据可以生成为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>
      

      私钥字符串应该(通过任何机制)保存到File(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编码的字符串。将此字符串保存到File(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,则表明该文件是合法的。

      最终笔记

      1. 加密仅确保使用私钥生成生成的数字签名。攻击者仍然可以覆盖应用程序的验证逻辑以读取恶意配置数据。
      2. 对配置文件的任何更改(包括添加注释,空格等)都将导致哈希变为无效。 GetFileSha1Hash的更专业化实现可能会在XML中搜索特定的键/值对,并仅对该数据进行签名,从而允许对配置文件进行其他修改。
      3. 使用GetFileSha1Hash的上述实现不可能将哈希本身包含在XML文件中,因为更新文件中的哈希本身会使先前的哈希无效。 GetFileSha1Hash的专门实现可以在生成配置文件哈希时忽略生成的哈希值,从而防止需要单独的配置文件。

答案 1 :(得分:0)

确定某些内容是否有变化的常用方法是采用“哈希”,例如,您可以采用MD5 hash配置或部分配置,然后每次检查时都会检查加载以确定它是否已被更改。