简体   繁体   English

验证ViewState MAC的安全解决方案失败

[英]Secure Solutions to Validation of ViewState MAC Failed

The Environment 环境

Okay, so I'm trying not to create a duplicate here, but I realize that this question has been sort of addressed before. 好的,所以我尝试不在此处创建重复项,但我意识到以前已经解决了该问题。

I've been doing a bunch of reading on the error: 我一直在阅读大量有关该错误的内容:

Validation of viewstate MAC failed. 验证视图状态MAC失败。 If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. 如果此应用程序由Web场或群集托管,请确保配置指定相同的validationKey和验证算法。 AutoGenerate cannot be used in a cluster. 自动生成不能在群集中使用。

I started getting the error after we upgraded our network monitoring software and SQL version. 升级网络监控软件和SQL版本后,我开始收到错误消息。

The page is an ASP.NET 4.0 web form external to the site it's being displayed on, written in C# with a bit of JavaScript and a fair bit of SQL. 该页面是显示该站点外部的ASP.NET 4.0 Web表单,以C#编写,带有一些JavaScript和一些SQL。 It also heavily uses .NET's chart forms (As in six chart areas on the chart, each with multiple series dynamically generated via SQL). 它还大量使用.NET的图表形式(在图表上的六个图表区域中,每个都有通过SQL动态生成的多个系列)。 We went from a free version of SQL Server 2008R2 to a trial of the full SQL Server 2012 instance and updated our SolarWinds Orion version to NPM 10.6. 我们从SQL Server 2008R2的免费版本到完整SQL Server 2012实例的试用版,将SolarWinds Orion版本更新为NPM 10.6。

The code is a large charting program which tracks the health of a variety of statistics averaged across each of our networks. 该代码是一个大型制图程序,可跟踪我们每个网络中平均的各种统计信息的运行状况。 The problem is, they asked for 'scrolling charts' which means auto-updating. 问题是,他们要求提供“滚动图表”,这意味着需要自动更新。 I'm using a form refresh instead of a meta or full postback because there are a wide variety of variables which allow the charts to stay on a specific statistic, network, page, and time window so that when the user leaves it alone, it will refresh and keep the view they were originally looking at. 我使用的是表单刷新,而不是元或完整回发,因为存在各种各样的变量,这些变量使图表可以保留在特定的统计信息,网络,页面和时间窗口上,以便用户单独使用时,将会刷新并保留他们最初查看的视图。 If it's not more than 5 minutes ago, it will keep updating. 如果还不到5分钟,它将继续更新。 All those values are being stored in the ViewState. 所有这些值都存储在ViewState中。 (Originally, it was even worse, being stored in hidden literals on the page). (本来会更糟,因为它存储在页面上的隐藏文字中)。

Updating the software didn't magically turn this into a web farm or cluster and we don't have a virtual environment, though we may soon. 更新软件并没有神奇地将其转变为Web场或群集,并且我们没有虚拟环境,尽管我们可能很快就会实现。

The Research 这项研究

I understand the problem is caused by the ViewState refreshing at an inconvenient time and causing the validation of the key to fail because the page loads out of sync with the validation algorithm. 我知道问题是由ViewState在不方便的时间刷新引起的,并且由于页面加载与验证算法不同步,导致键的验证失败。 I've seen a lot of similar questions and answers like these: 我见过很多类似的问题和答案,例如:

ASP.NET Validation of viewstate MAC failed ASP.NET验证视图状态MAC失败

Validation of viewstate MAC failed when on page for 20+ minutes 页面上显示20分钟以上时,viewstate MAC的验证失败

ScriptResource error: am I being hacked? ScriptResource错误:我是否被黑了?

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

Admittedly, this isn't customer facing, but per Microsoft: 诚然,这不是面向客户的,但对于Microsoft:

This attribute should never be set to false in a production Web site, even if the >application or page does not use view state. 即使>应用程序或页面不使用视图状态,也不应在生产网站中将此属性设置为false。 The view state MAC helps ensure the security >of other ASP.NET functions in addition to view state. 视图状态MAC除了视图状态外,还有助于确保其他ASP.NET功能的安全性。

My Question: 我的问题:

All of these answers seem to have the same solution and I'm not convinced that those are good solutions. 所有这些答案似乎都具有相同的解决方案,但我不认为这些都是好的解决方案。 What alternatives do I have? 我有什么选择? My superior and I don't think setting the key is good from a security standpoint. 我的上司,从安全角度来看,我认为设置密钥并不好。 I'm willing to tweak the code to store things a different way. 我愿意调整代码以其他方式存储事物。 I've had to use session state elsewhere, but I'm still new to it. 我不得不在其他地方使用会话状态,但是我还是新手。 Would that run into a similar problem with refreshing before some sort of validation takes place? 在进行某种验证之前,刷新是否会遇到类似的问题? Can I force the refresh to run more slowly? 我可以强制刷新运行更慢吗? I've also seen something about altering where the key validation happens. 我还看到了一些有关更改密钥验证发生位置的信息。 How is that solution from a security standpoint? 从安全角度来看,该解决方案如何?

First off, I was finally able to track down my error. 首先,我终于能够找到我的错误。 It turned out that I was actually managing to create a SQL Server deadlock which in turn meant that my .Net charts were throwing an un-handled NullReference Exception (derp). 原来,我实际上是在设法创建SQL Server死锁,这又意味着我的.Net图表抛出了未处理的NullReference Exception(derp)。

All right, so, there are only a few alternatives to ViewState in ASP.NET. 好的,因此,ASP.NET中的ViewState仅有几种选择 I finally got my page working, so I'm leaving this here for anyone who randomly happens across it. 我终于使我的页面正常工作了,所以我把这里留给随机出现在它上面的任何人。

One of the alternatives you see here on SO is to just set the machine key and enable the MAC State like so: 您在SO上看到的替代方法之一是仅设置机器密钥并启用MAC状态,如下所示:

<pages enableViewStateMac="true">

and then: 接着:

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

I was moderately concerned about this for security reasons, but I couldn't make any other solution work. 出于安全原因,我对此有所关注,但无法使用其他任何解决方案。 The conclusion I eventually came to was that I would just statically set it and re-generate the machine keys on a regular based on 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();
        }
    }

This didn't totally solve my problem, though. 但是,这并不能完全解决我的问题。 What I ended up doing was, for the charts which have a lookup page, I added a try catch to my larger SQL queries and, despite reservations from posts like this and similar concerns with WITH(NOLOCK) on Stack Overflow , we decided that the possible pitfalls fell within acceptable error margin parameters. 我最终要做的是,对于具有查找页面的图表,我在较大的SQL查询中添加了一个try catch,并且尽管有这样的帖子有所保留,并且在Stack Overflow上对WITH(NOLOCK)有类似的关注,我们还是决定可能的陷阱落在可接受的误差容限参数范围内。

In the page which actually cares about the Session ID, I had to force the program to halt briefly and return to the lookup page. 在实际上关心会话ID的页面中,我不得不强制程序暂时停止并返回到查找页面。 Interestingly enough, it didn't crash at all with me logged out and the charts refreshing every two minutes over night. 有趣的是,当我注销时,它一点也没有崩溃,并且每隔两分钟刷新一次图表。 The page that doesn't use the Session ID still has a throw-away variable set like this on the main page: 在不使用会话ID的页面上,仍在主页上设置了以下丢弃变量:

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

And this in the control for the solution to work properly: 并且此控件在解决方案中可以正常工作:

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

The Catch on this page simply redirects back to itself. 此页面上的Catch只是将其重定向回自身。 The one with a search page caused a reference loop problem as the session state (which the page relied on to generate the charts) was empty and therefore broke the charts. 带有搜索页面的页面导致了一个参考循环问题,因为会话状态(页面用来生成图表的页面状态)为空,因此破坏了图表。 I don't know that this will help anyone, but both the charts which use session state and those which don't require it are finally working after a network upgrade. 我不知道这会对任何人有帮助,但是使用会话状态的图表和不需要会话状态的图表最终都可以在网络升级后正常工作。 Cheers! 干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM