关于c#:CryptographicException:填充无效且无法删除,并且viewstate MAC验证失败

CryptographicException: Padding is invalid and cannot be removed and Validation of viewstate MAC failed

监视我的全局异常日志这个错误似乎是不可能消除的,无论我做什么,我认为我终于摆脱了它,但它又回来了。你可以在类似的帖子上看到错误的痕迹。

环境注意事项:

IIS 6.0、.NET 3.5 SP1单服务器ASP.NET应用程序

已采取的步骤:

1
2
3
4
  <system.web>
    <machineKey validationKey="big encryption key"
      decryptionKey="big decryption key"
      validation="SHA1" decryption="AES" />

在我所有页面的页面库中

1
2
3
4
5
6
  protected override void OnInit(EventArgs e)
  {
    const string viewStateKey ="big key value";

    Page.ViewStateUserKey = viewStateKey;
  }

另外,在页面的源代码中,我可以看到所有ASP.NET生成的隐藏字段都正确地位于页面的顶部。


首先,让我们从这样一个事实开始:视图状态的错误发生在回发上。

而且我必须说,我已经做了所有人建议做的事情来避免这个问题。我有一台机器,但有两个运行相同页面的池。

所以有人通过"点击"你的页面来做一个动作,比如一个人,或者其他搜索机器,或者一些黑客试图检查你的系统是否有问题…

我也有类似的问题(很少但存在的问题),最后我发现人们试图对我的页面进行黑客测试。(来自我拥有的同一个IP和DoS攻击)

我修改了函数loadPageStateFromPersistenceMedium()来转换视图状态,并通过记录输入的内容以及IP的内容来查看…然后我开始监视这些结果,并看到视图状态被手动更改——或者完全是空的。

出错时,我只是将他重定向到同一页…

这是我做的……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public abstract class BasePage : System.Web.UI.Page
{
    protected override object LoadPageStateFromPersistenceMedium()
    {
        try
        {
            .. return the base, or make here your decompress, or what ever...
            return base.LoadPageStateFromPersistenceMedium();            
        }
        catch (Exception x)
        {
            string vsString = Request.Form[__VIEWSTATE];
            string cThePage = Request.RawUrl;

            ...log the x.ToString() error...
            ...log the vsString...
            ...log the ip coming from...
            ...log the cThePage...

        // check by your self for local errors
            Debug.Fail("Fail to load view state ! Reason:" + x.ToString());
        }

        // if reach here, then have fail, so I reload the page - maybe here you
        // can place somthing like ?rnd=RandomNumber&ErrorId=1 and show a message
        Responce.Redirect(Request.RawUrl, true);        

        // the return is not used after the redirect
        return string.Empty;
    }    
}

第二理由

现在还有一个原因可以解释为什么会发生这种情况,原因是在加载uu eventvalidation之前,有人单击了您的页面。

即使在找到ASP.NET的最后一个按钮上也会放置此事件验证,如果在页面上或按钮附近的许多位置上都有一些事件验证,则会转到页面的末尾。

所以,即使您在页面顶部看到视图状态,验证在哪里????也许这个从未加载过-页面损坏?,用户点击页面的速度太快?

1
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" ... >

为了避免这种问题,我制作了一个简单的javascript,除非加载了这个输入,否则我不会让它按下按钮!!!!.

还有一条评论,事件验证并不总是出现的!因此,如果您制定了一个通用的解决方案,那么不搜索这个字段可能更安全,但是要使用一个javascript技巧来检查是否加载了整个页面,或者您认为的其他内容。

这是jquery的最终解决方案:(请注意,如果存在eventvalidation,我会检查pageload!)我把这个放在我的主页上了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script language="javascript" type="text/javascript">
    function AllowFormToRun()
    {
        var MyEventValidation = $("#__EVENTVALIDATION");

        if(MyEventValidation.length == 0 || MyEventValidation.val() ==""){
            alert("Please wait for the page to fully loaded.");
            return false;
        }

        return true;
    }      


protected void Page_Load(object sender, EventArgs e)
{
    // I do not know if Page can be null - just in case I place it.
    if (Page != null && Page.EnableEventValidation)
    {
        Form.Attributes["onsubmit"] ="return AllowFormToRun();";
    }
}

您可以通过在页面按钮附近放置一个延迟来进行测试。

1
<% System.Threading.Thread.Sleep(5000); %>

更新

今天,我在日志中再次看到了这个消息,我发现一个bot获取页面并使链接上的所有字符(小写),包括参数,所以这是另一个不获取正确编码字符串的原因,抛出像padding这样的消息是无效的,不能删除。

希望这对你有更多的帮助。


一项对网页的调查发现,错误信息中有几个关键词,这表明这种类型的错误是相对常见的,通常是随机的(至少在外观上),不幸的是很少包括一个明确的工作或解释…

许多相似但不同的情况的存在可能与许多不同的体系结构和底层配置有关,这可能导致加密层无法在请求页中断言MAC(消息身份验证代码)的真实性:

  • 服务器场设置
  • 跨域/联合页面
  • 第三方小工具库等
  • 实际的ASP程序逻辑(当然)

关于这些bug报告,一个相对频繁的"标记"是提到资源请求(例如webresource.axd)。请注意,这些请求通常不会被记录(以免它们会随着相对不感兴趣的事件而膨胀日志文件的大小)。日志文件中的这种缺失以及它们经常被缓存的事实(因此,错误的相对随机性和不经常发生)可能解释了错误的可能来源是如何"被监视"的。这也表明,在尝试重新创建bug时(在日志中跟踪,实时等),防止Web浏览器缓存(或者至少在最初清除它缓存)可能很有用。

简而言之,这里有一些想法和事情需要寻找:

  • 开始记录*.axd请求
  • 尝试将此类AXD请求与异常日志中的错误事件关联起来。
  • 查找包含资源引用的网页
  • 如果在服务器场设置中,请确保所有实例都使用相同的密钥(显然,问题中提供的代码片段提示了多个IIS服务器)
  • 对与第三方关联的页面(搜索服务、关联程序…)持怀疑态度

希望这有帮助;—)


您确定您的问题与加密有关,而不是由超大的视图状态引起的吗?如果问题是viewstate,则可以对其进行分组-在web.config中更改pages/maxpagestatefieldlength的值