buguge - Keep it simple,stupid

知识就是力量,但更重要的,是运用知识的能力why buguge?

导航

System.Web.HttpException (0x80004005): 验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate。

异常描述:

Global.asax捕获到异常:
System.Web.HttpException (0x80004005): 验证视图状态 MAC 失败。如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法。不能在群集中使用 AutoGenerate。 http://go.microsoft.com/fwlink/?LinkID=314055 ---> System.Web.UI.ViewStateException: 无效的视图状态。 Client IP: 10.0.0.172 Port: 52033 Referer: http://pcentertest.shenbianhui.cn/Test/WebForm1.aspx Path: /Test/WebForm2.aspx User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 ViewState: /wEPDwULLTE0MTM1MTM2MTRkZPqYgjmljF6+HgGibehV9ktjHcPeFSdh7aSGX+FPeAP/ 在 System.Web.UI.ViewStateException.ThrowMacValidationError(Exception inner, String persistedState) 在 System.Web.UI.ObjectStateFormatter.Deserialize(String inputString, Purpose purpose) 在 System.Web.UI.Util.DeserializeWithAssert(IStateFormatter2 formatter, String serializedState, Purpose purpose) 在 System.Web.UI.HiddenFieldPageStatePersister.Load() 在 System.Web.UI.Page.LoadPageStateFromPersistenceMedium() 在 System.Web.UI.Page.LoadAllState() 在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 在 System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 在 System.Web.UI.Page.ProcessRequest() 在 System.Web.UI.Page.ProcessRequest(HttpContext context) 在 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 在 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

 

同一个站点内两个页面WebForm1.aspx和WebForm2.aspx。

WebForm1.aspx里是一个服务器表单控件,其form的action指向的是WebForm2.aspx。如下是WebForm1.aspx的html,WebForm2是一个空的表单。

<form id="form1" runat="server" action="WebForm2.aspx">
    <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
    <asp:Button ID="btn1" runat="server" Text="submit"/>
</form>

本地测试是正常的。线上是nginx部署的,在提交表单时出现了上面的异常。 去年自打线上用了nginx后,这样的异常就不断来做客了。

访问WebForm1时的网页源代码: 

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>

</title></head>
<body>
    <form method="post" action="WebForm2.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE0MTM1MTM2MTRkZPqYgjmljF6+HgGibehV9ktjHcPeFSdh7aSGX+FPeAP/" />
</div>

<div class="aspNetHidden">

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAM2KkFwpZuLdd2aQa8ABSbJscfOVKgi+tKUa7rIRxwonUaz6Rs6w/mRtFpOGK59+RYCc553OHEnOJ0ehwkaFMWSNbUfXJpnRIAKLupf12VoZA==" />
</div>
        <div>
            <input name="txt1" type="text" id="txt1" />
            <input type="submit" name="btn1" value="submit" id="btn1" />
        </div>
    </form>
</body>
</html>

 

 

 

 

网上查了一些资料。

 

有说是禁用viewstate是可以解决的。 这里,我新建了个WebForm1.html文件,然后,把WebForm1.aspx生成的html去掉asp.net生成的viewstate隐藏域后放到WebForm1.html里,这样访问WebForm1.html,是可以把form表单的数据提交到WebForm2.aspx的。

不过,不管怎么尝试,当访问WebForm1.aspx时,总是阻挡不了它生成viewstate隐藏域的脚步。

 

先把问题记录下来。此后,还需再进一步处理。

 

ref:http://www.cnblogs.com/Setme/archive/2012/06/05/2537084.html

 

--------------------------------------------------------------后续20170426---------------------------------------------------------

今天项目上线,趁有些时间,就找运维着重解决一下这个顽固的问题。

运维在服务器主机上直接通过ip+端口的形式来访问页面,也同样会出现这个异常。看来,我是误认为与nginx有关了。

这里说明一下自己的大意,前几天都是视图从WebForm1上尝试解决问题的,而现在仔细看了一下异常信息,异常是在WebForm2表单抛出来的。所以,要解决问题也得从WebForm2来入手。

参考的网页说:一般而言是因为你的某些操作修改了视图状态,我猜测你可能使用了ajax并在客户端用javascript动态添加了某些项。 

而WebForm2是个空的表单,actually,即使去掉form空留一个<body></body>,也还是会报那个异常。

不过,按它说的,在WebForm2的@page里加了一个EnableViewStateMac="false",就不出现那个异常了。

问题是解决了,不过还是搞不明白,同样的代码,为什么测试环境没问题,而生产上有这个异常呢?  运维同事也说可能是程序的漏洞,并不认为是服务器的问题。每个人都有护犊子的情节,当然解决问题要从客观的角度来分析。

 

--------------------------------------------------------------后续20170426---------------------------------------------------------

接下来有必要了解一下EnableViewStateMac

EnableViewStateMac是asp.net内置的安全利器之一。

微软官方对Page.EnableViewStateMac 属性的定义:

Gets or sets a value indicating whether ASP.NET should check message authentication codes (MAC) in the page's view state when the page is posted back from the client.

什么意思呢?

需要先说一下大家熟知的ViewState:http请求本身是无状态的,而视图状态则是用于在对同一个页的两个连续请求之间保持控件的状态。

再来看看EnableViewState:

获取或设置一个值,该值指示当前页请求结束时该页是否保持其视图状态以及它包含的任何服务器控件的视图状态。

如果该页保持其视图状态,则为 true;否则为 false。默认为 true。

即使 EnableViewState 为 false,ASP.NET 用于检测回发的页中也可能呈现隐藏的视图状态字段。

好,接下来就可以介绍EnableViewStateMac了:

获取或设置一个值,该值指示当页从客户端回发时,ASP.NET 是否应对页的视图状态运行消息验证检查 (MAC)。

当 EnableViewStateMac 属性设置为 true 时,将检查编码和加密的视图状态以验证该视图状态在客户端上是否未被篡改。 为了保证安全,asp.net默认设置EnableViewStateMac为true。

 

视图状态用于在对同一个页的两个连续请求之间保持控件的状态。默认情况下,视图状态是 Base64 编码的,并使用一个哈希值签名,以防止篡改。除非更改默认的页设置,否则不可能篡改视图状态。如果攻击者修改了视图状态,甚至使用正确的算法重新生成了视图状态,ASP.NET 都会捕获这些尝试并引发异常。视图状态被篡改并不一定有害,虽然它修改了服务器控件的状态 —— 但可能成为造成严重感染的工具。因此,不移除默认情况下进行的计算机身份验证代码 (MAC) 交叉检查就非常重要。请参阅图 2。



图 2. 启用 EnableViewStateMac 时,使视图状态本身难以篡改的因素

启用了 MAC 检查时(默认情况),将对序列化的视图状态附加一个哈希值,该值是使用某些服务器端值和视图状态用户秘钥(如果有)生成的。回发视图状态时,将使用新的服务器端值重新计算该哈希值,并将其与存储的值进行比较。如果两者匹配,则允许请求;否则将引发异常。即使假设黑客具有破解和重新生成视图状态的能力,他/她仍需要知道服务器存储的值才可以得出有效的哈希。

 

ref:利用 ASP.NET 的内置功能抵御 Web 攻击http://www.51cto.com/specbook/14/3232.htm

ref验证视图状态 MAC 失败的处理办法总结!http://blog.sina.com.cn/s/blog_3f42ab160100kv2v.html

posted on 2017-04-17 21:47  buguge  阅读(2282)  评论(0编辑  收藏  举报