【问题标题】:CryptographicException: Padding is invalid and cannot be removed and Validation of viewstate MAC failedCryptographicException:填充无效且无法删除,并且视图状态 MAC 验证失败
【发布时间】:2009-11-30 17:38:43
【问题描述】:

监控我的全局异常日志,无论我做什么,这个错误似乎都无法消除,我以为我终于摆脱了它,但它又回来了。您可以在similar post here 上看到错误的轨迹。

环境注意事项:

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

已经采取的步骤:

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

在我所有页面的页面库中

  protected override void OnInit(EventArgs e)
  {
    const string viewStateKey = "big key value";

    Page.ViewStateUserKey = viewStateKey;
  }

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

【问题讨论】:

  • 错误是一致的还是间歇性的?
  • 非常断断续续,至今无法重现。
  • 今天我再次在日志中看到这条消息用于 webresource,我发现一个机器人获取页面并将链接上的所有字符都设为小写,包括参数,所以这是另一个没有得到正确编码字符串的原因,并抛出像 Padding is invalid and cannot be removed 这样的消息。

标签: c# asp.net unhandled-exception cryptographicexception


【解决方案1】:

首先让我们从 这种视图状态错误发生在 PostBack 上的事实开始。

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

所以某人做了一个动作,通过“点击”你的页面来寻找一个人,或者其他一些搜索机器,或者一些黑客试图检查你的系统是否有问题......

我有类似的问题(罕见但存在),我终于发现人们试图对我的网页进行黑客测试。 (来自我拥有的同一个 IP 和 dos 攻击)

我修改函数 LoadPageStateFromPersistenceMedium() 转换视图状态,并通过记录输入的确切内容以及来自哪些 IP 来查看...然后我开始监控这些结果并看到视图状态是手动更改的 - 或者完全是空的。

出错时我只是将他重定向到同一页面...

这就是我所做的......

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;
    }    
}

第二个原因

现在发生这种情况还有一个原因,原因是在加载 __EVENTVALIDATION 之前有人单击了您的页面。

这个 eventValidation 被放置在最后一个按钮上——即使是 asp.net 找到的那个按钮,如果你在页面上的很多地方,或者按钮附近有一些,那么这个到页面的末尾。

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

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

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

还有一条评论,__EVENTVALIDATION 并不总是存在!因此,如果您制定通用解决方案,则不要搜索此字段可能更安全,而是制作一个 javascript 技巧来检查是否已加载整个页面,或者您认为的其他内容。

这是我使用 jQuery 的最终解决方案:(请注意,如果 eventvalidation 存在,我会检查 PageLoad!)。我把它放在我的 MasterPages 上。

<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; 
    }       
</script>

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();";
    }
}

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

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

更新

今天我在日志中再次看到 WebResource 的这条消息,我发现机器人获取页面并将链接上的所有字符都设为小写,包括参数,所以这是没有得到正确编码字符串的另一个原因,并抛出类似 Padding is invalid and cannot be removed.

之类的消息。

希望这对您有更多帮助。

【讨论】:

  • 这很难选择接受哪个答案。由于原因#1,我接受了您的回答。我从未考虑过在 try/catch 中为 ASP.NET 包装 base. 方法调用来接管此类错误的执行,我认为这可能非常有用。第二个原因应该很少再成为一个因素,在 3.5 框架中,他们通过在页面上插入非常高的 EventValidation 字段来解决这个错误。这发生在我进行任何内容渲染之前。
  • 首先感谢您的投票。其次,我想说 EventValidation 在页面底部有一段时间。 EventValidation 需要读取一页中的所有事件,并且在某些情况下(至少在我的页面中)框架直到渲染页面的大部分时才知道它......所以请查看页面的源代码以检查在哪里事件验证是。在我的页面中位于底部或中间。
  • 伟大的建议,Aristos!我们(我)总是考虑使用现场设备(如果不是事后设备)来诊断这些问题,但是在可行的情况下(考虑到对生产服务器的影响),在 BasePage 中捕获异常会消除很多猜测!谢谢和+1!
【解决方案2】:

对包含错误消息中的几个关键字的网页进行的调查表明,这种类型的错误相对常见,通常是随机的(至少在外观上),不幸的是很少包含明确的解决方法或解释...

许多相似但不同的情况的存在可能与许多不同的架构和底层配置有关,这可能会导致加密层无法断言 MAC(消息验证码)在请求页面:

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

围绕这些错误报告的一个相对频繁的“标记”是提及资源请求(例如,WebResource.axd)。
请注意,此类请求通常不记录(以免它们因相对不感兴趣的事件而膨胀日志文件大小)。日志文件中的这种缺失以及它们经常被缓存的事实(因此错误的相对随机和不经常发生)可以解释错误的这种可能起源如何“在雷达之下”。这也表明,在尝试重新创建错误时(同时在日志中进行实时跟踪等),防止 Web 浏览器缓存(或至少在最初清除缓存)可能很有用。

简而言之,这里有一些想法和需要寻找的东西:

  • 开始记录 *.axd 请求
  • 尝试将此类 axd 请求与异常日志中的错误事件关联起来
  • 查找包含资源引用的页面
  • 如果在 Farm 设置中,请确保所有实例使用相同的密钥(显然问题中提供的 sn-p 提示在多个 IIS 服务器上)
  • 对带有 3rd 方关联(搜索服务、联属网络营销计划...)的网页保持警惕

希望这会有所帮助;-)

【讨论】:

    【解决方案3】:

    您确定您的问题与密码学有关,而不是由过大的 ViewState 引起的吗? 如果 ViewState 是问题所在,您可以对其进行分块 - 在 web.config 中更改 pages / MaxPageStateFieldLength 的值

    【讨论】:

    • 我从未见过有人提到这个错误可能来自一个太大的视图状态但是看起来这将是一个非常容易重现的错误,我会尝试粘贴一个巨大的对象进入我的页面,看看是否会导致这种情况。
    猜你喜欢
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 2016-07-18
    • 2011-05-31
    • 2014-06-17
    • 1970-01-01
    • 2021-03-15
    • 2011-12-25
    相关资源
    最近更新 更多