8.3.3 状态管理的错误配置

我们在第5章中专门讨论了会话管理攻击和对策,但是还为本小节保留了由于错误配置而产生的这种漏洞的一个简短例子。

破解ViewState

ViewState是一个ASP.NET方法,用于维护ASP.NET网页中所有项目的“状态”信息(更多关于ViewState信息的链接参见“参考与延伸阅读”)。在旧版本的ASP中,当Web表单提交到服务器时,所有表单值被清空。在ASP.NET中提交同样的表单时,表单的状态或者“ViewState”得到维护。我们都曾经碰到这种令人沮丧的情况:在完成和提交一个很长的申请表或者其他Web表单之后,接收到一个错误信息并且看到输入表单的所有信息消失。这一般是发生在某个域留空或者不符合应用程序期待的结构时。应用不能维持提交的表单的“状态”。ViewState的目标就是通过维护已提交到服务器的表单的内容来消除这个问题——如果发生了错误或者在一个表单里有预期之外的值,仅仅要求用户更正这部分信息,表单的其余部分保持不变。

ViewState还可以用于保存其他应用值的状态。许多开发人员将敏感信息和全部对象保存在ViewState中,但是如果ViewState遭到篡改,这种做法可能造成严重的安全问题。

Microsoft参考应用Duwamish 7.1(“参考与延伸阅读”中有这个应用的链接)中有这个问题的一个很好的例子。Duwamish Books是一个网上购书应用的示例。图8-9显示了Duwamish Books的基本外观。注意,《How to Win Friends and Influence People》这本书的售价为11.99美元。

图8-9 Microsoft的Duwamish示例Web应用

查看图8-10中该页面的源代码,可以看到单击“Add to Cart”按钮提交页面表单内容时,发送了一个隐藏的ViewState域。这个隐藏的ViewState域如图8-10中黑色部分所示。你可以看到,ViewState域的值经过了编码。尽管仅从该值上很难看出使用了什么编码算法,但是大部分Web技术使用Base64编码,所以可以假定这里也使用Base64。为了了解这个ViewState域的属性,我们让这个值通过一个Base64解码器。结果如图8-11所示。

图8-10 ViewState位于表单中的一个隐藏标记里

图8-11 Base64解码后的ViewState

关于图8-11中所示的解码后的ViewState值,有两点要注意:

·价格11.99美元保存在ViewState中。

·ViewState没有进行散列计算。你可以通过查看解码字符串的最后部分知道这一点,这里可以看到一个向右的尖括号(>)。经过散列计算的ViewState在字符串最后有如下形式的随机字节:<:Xy'y_w_Yy/FpP。

因为这个ViewState没有进行散列计算,对它的修改应该很容易被Web应用所接受。攻击者可以将价格从11.99美元改成0.99美元,然后将请求编码为Base64,提交给服务器。这样一个请求如图8-12所示。

图8-12 破解后发送给服务器的请求

这里看到的服务器响应,表示该书可以用攻击者设置的0.99美元的价格订购!

ViewState破解对策

首先,不要在ViewState中保存任何内容。让ViewState做自己的工作,不要打扰它。这是阻止攻击者用它对付用户最容易的方法。

Microsoft提供了为ViewState标记应用一个密钥Hash的功能。这个Hash在接收的时候检查,确保ViewState在传输中没有被修改。根据你的ASP.NET版本,这种ViewState完整性校验机制可能默认启用。如果没有启用,你可以在应用的Web.config文件中添加如下设置来启用完整性检查(粗体文本的内容启用ViewState完整性检查):


<pages buffer="(true|false)" enableViewStateMac="true"/> <machineKey
validationKey="(minimum 40 char key)" decryptionKey=
"AutoGenerate" validation="SHA1"/>

密钥可以在Web.config中手工输入,或者将validationKey设置为AutoGenerate,自动生成密钥。如果你希望每个应用都有唯一的密钥,可以为validationKey值加上IsolateApps修饰符。web.config的<machineKey>元素的更多信息可以通过本章结尾处的“参考与延伸阅读”小节中的链接找到。

提示  如果你有一个服务器场,可能希望在所有服务器中设置相同的ViewState校验密钥,而不是让每个服务器自动生成(这会破坏你的应用)。