【问题标题】:Secure Solutions to Validation of ViewState MAC Failed验证 ViewState MAC 的安全解决方案失败
【发布时间】:2013-10-15 14:12:00
【问题描述】:

环境

好的,所以我试图不在这里创建重复,但我意识到这个问题之前已经解决了。

我一直在对错误进行大量阅读:

视图状态 MAC 验证失败。如果此应用程序由 Web Farm 或集群托管,请确保配置指定相同的 validationKey 和验证算法。 AutoGenerate 不能在集群中使用。

我在升级网络监控软件和 SQL 版本后开始出现错误。

该页面是一个 ASP.NET 4.0 Web 表单,位于它所显示的站点之外,用 C# 编写,带有一些 JavaScript 和相当多的 SQL。它还大量使用 .NET 的图表形式(如图表上的六个图表区域,每个区域都有多个通过 SQL 动态生成的系列)。我们从 SQL Server 2008R2 的免费版本升级到完整 SQL Server 2012 实例的试用版,并将 SolarWinds Orion 版本更新到 NPM 10.6。

该代码是一个大型图表程序,用于跟踪我们每个网络中各种统计数据的平均运行状况。问题是,他们要求“滚动图表”,这意味着自动更新。我使用表单刷新而不是元或完整回发,因为有各种各样的变量允许图表停留在特定的统计数据、网络、页面和时间窗口上,这样当用户不理会它时,它将刷新并保留他们最初查看的视图。如果它不超过 5 分钟前,它将不断更新。所有这些值都存储在 ViewState 中。 (原本更糟糕的是,被存储在页面上的隐藏文字中)。

更新软件并没有神奇地把它变成一个网络农场或集群,而且我们没有虚拟环境,尽管我们可能很快就会。

研究

我了解此问题是由于 ViewState 在不方便的时间刷新并导致密钥验证失败,因为页面加载与验证算法不同步。我见过很多类似的问题和答案:

ASP.NET Validation of viewstate MAC failed

Validation of viewstate MAC failed when on page for 20+ minutes

ScriptResource error: am I being hacked?

http://aspadvice.com/blogs/joteke/archive/2006/02/02/15011.aspx

诚然,这不是面向客户的,而是按照 Microsoft 的要求:

在生产网站中,该属性永远不应设置为 false,即使应用程序或页面不使用视图状态也是如此。视图状态 MAC 有助于确保除视图状态之外的其他 ASP.NET 功能的安全性。

我的问题:

所有这些答案似乎都有相同的解决方案,我不相信这些都是好的解决方案。我有什么选择?从安全的角度来看,我的上司和我认为设置密钥并不好。我愿意调整代码以不同的方式存储东西。我不得不在其他地方使用会话状态,但我还是新手。在进行某种验证之前是否会遇到类似的刷新问题?我可以强制刷新运行得更慢吗?我还看到了一些关于更改密钥验证发生位置的内容。从安全角度来看,该解决方案如何?

【问题讨论】:

    标签: c# asp.net sql-server-2012 viewstate


    【解决方案1】:

    首先,我终于能够找到我的错误。事实证明,我实际上是在设法创建一个 SQL Server 死锁,这反过来意味着我的 .Net 图表抛出了一个未处理的 NullReference 异常 (derp)。

    好吧,所以,在 ASP.NET 中只有几个 alternatives to ViewState。我终于让我的页面正常工作了,所以我把它留在这里给任何偶然发生的人。

    您在 SO 上看到的其中一种替代方法是仅使用 set the machine key 并启用 MAC 状态,如下所示:

    <pages enableViewStateMac="true">
    

    然后:

    <machineKey 
      validationKey="[128 Hex Number]"
      decryptionKey="[64 Hex Number" 
      validation="SHA1" 
      decryption="AES" />
    

    出于安全原因,我对此有点担心,但我无法使用任何其他解决方案。我最终得出的结论是,我只需静态设置它并根据Microsoft's example code定期重新生成机器密钥:

        static void Main(string[] argv)
        {
            //128 Hex characters for the validation key, 64 for the AES decryption key
            int hexLengthForEncryption = 128;
    
            string validationKey = Generate_New_Key(hexLengthForEncryption, argv);
    
            hexLengthForEncryption = 64;
    
            string decryptionKey = Generate_New_Key(hexLengthForEncryption, argv);
    
            string[] originalKeys = new string[2] {validationKey, decryptionKey};
    
            Generate_File(originalKeys);
    
            Console.WriteLine("The file has been generated. Would you like to generate new keys in a new file?");
    
            string yorn = Console.ReadLine();
    
            while ((yorn != "N") && (yorn != "n") && (yorn != "no") && (yorn != "No"))
            {               
                hexLengthForEncryption = 128;
                validationKey = Generate_New_Key(hexLengthForEncryption, argv);
                hexLengthForEncryption = 64;
                decryptionKey = Generate_New_Key(hexLengthForEncryption, argv);
    
                string[] freshLines = new string[2]{validationKey, decryptionKey};
    
                Generate_File(freshLines);
    
                Console.WriteLine("The file has been generated. Would you like to generate new keys to a new file?");
    
                yorn = Console.ReadLine();
            }
        }
    

    不过,这并没有完全解决我的问题。我最终做的是,对于具有查找页面的图表,我在较大的 SQL 查询中添加了一个 try catch,尽管有reservations from posts like thisWITH(NOLOCK) on Stack Overflow 的类似问题,我们认为可能的陷阱属于可接受的错误边距参数。

    在真正关心会话 ID 的页面中,我不得不强制程序暂时停止并返回查找页面。有趣的是,当我登出并且图表每两分钟刷新一次时,它根本没有崩溃。不使用 Session ID 的页面在主页面上仍然有这样的一次性变量设置:

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            ViewStateUserKey = Session.SessionID;
        }
    

    这在控制中使解决方案正常工作:

            //This variable is necessary to having a session state persist across postbacks, but is otherwise useless
            Session["Throwaway"] = DateTime.Now;
    

    此页面上的 Catch 只是重定向回自身。带有搜索页面的页面导致了引用循环问题,因为会话状态(页面依赖于生成图表)是空的,因此破坏了图表。我不知道这会对任何人有所帮助,但是使用会话状态的图表和不需要会话状态的图表最终都在网络升级后工作。干杯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多