前言
在一次测试过程中遇到了这个ViewState的反序列化漏洞,当时对于利用方式以及原理都不太清楚,因此有了这边文章,学习一下viewstate的漏洞原理以及利用方式。
ViewState基础介绍
ViewState机制
ViewState 是 ASP.NET(Active Server Pages .NET)框架用来保持页面状态的一种机制。ASP.NET 是微软开发的用于动态网页服务器端开发的框架,ViewState 是其中用于维护和管理页面状态的一部分。它在客户端和服务器之间存储页面和控件的状态。
问题1:ViewState是在页面生成的时候创建的吗?
ViewState原始状态是一个 字典类型。在响应一个页面时,ASP.NET 会把所有控件的状态序列化为一个字符串,然后作为 hidden input 的值 插入到页面中返还给客户端。当客户端再次请求时,该hidden input 就会将ViewState传给服务端,服务端对ViewState进行反序列化,获得属性,并赋给控件对应的值。
问题2:可以举个例子保存了什么样的页面状态?
假如服务端在处理第n+1次请求时,想使用第n次传给服务器的值进行计算,而这时第n次请求所对应的page实例早已被销毁,要去哪里找上一次传给服务器的值呢?为了满足这种需求,就出现了多种状态管理技术,而VewState正是ASP.NET 所采用的状态管理技术之一。
ViewState工作原理
1)保存页面状态:每次页面请求和响应,服务器端控件的状态信息需要保存在客户端,待下一次请求时恢复。ViewState 就是在页面生成过程中将控件状态编码并嵌入到页面的隐藏字段中。
2)在客户端存储和传输:ViewState 的数据以 Base64 编码格式存储在页面中的一个名为 __VIEWSTATE 的隐藏字段里,随每次表单提交一起传输到服务器。
3)恢复页面状态:页面在提交到服务器后,ASP.NET 会将 __VIEWSTATE 字段的数据提取出来进行解码并恢复控件的状态
实现细节
在典型的 ASP.NET 页面上,ViewState 数据通常类似如下:
<form id="form1" runat="server"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="dDwtNzI4MjcyOTUzO3Q8O2w8aTwxPjs+" /> <!-- 其他表单控件 --> </div> </form>
__VIEWSTATE 的 value 属性存储了编码后的数据,这些数据包含了控件的状态信息。
如下面的一个VIEWSTATE信息,包含了一个时间戳
出现viewstate的原因
HTTP模型是无状态的,这意味着,每当客户端向服务端发起一个获取页面的请求时,都会导致服务端创建一个新的page类的实例,并且一个往返之后,这个page实例会被立刻销毁。假如服务端在处理第n+1次请求时,想使用第n次传给服务器的值进行计算,而这时第n次请求所对应的page实例早已被销毁,要去哪里找上一次传给服务器的值呢?为了满足这种需求,就出现了多种状态管理技术,而VewState正是ASP.NET 所采用的状态管理技术之一。
viewstate保证安全性的方式
viewstate里面可能保存了敏感信息,因此为了防止信息泄露和篡改,引入了加密和签名的机制。
原始的ViewState仅仅是用base64编码了序列化后的binary数据,未使用任何类型的密码学算法进行加密,可以使用LosFormatter(现在已经被ObjectStateFormatter替代)轻松解码和反序列化。
LosFormatter formatter = new LosFormatter(); object viewstateObj = formatter.Deserialize("/wEPDwULLTE2MTY2ODcyMjkPFgIeCHBhc3N3b3JkBQlzd29yZGZpc2hkZA==");
反序列化的结果实际上是一组System.Web.UI.Pair对象。
引入加密机制
为了保证ViewState不会发生信息泄露,ASP.NET 2.0 使用 ViewStateEncryptionMode属性 来启用ViewState的加密,该属性可以通过页面指令或在应用程序的web.config 文件中启用。
<%@ Page ViewStateEncryptionMode="Always" %>
ViewStateEncryptionMode 可选值有三个:Always、Never、Auto
引入签名机制
加密不能防止篡改 ,即使使用加密数据,攻击者仍然有可能翻转加密书中的位。所以要使用数据完整性技术来减轻篡改威胁,即使用哈希算法来为消息创建身份验证代码(MAC)。可以在web.config 中通过EvableViewStateMac来启用数据校验功能。
<%@ Page EnableViewStateMac="true" %>
注意:从.NET 4.5.2 开始,强制启用ViewStateMac 功能,也就是说即使你将 EnableViewStateMac设置为false,也不能禁止ViewState的校验。安全公告KB2905247(https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2013/2905247?redirectedfrom=MSDN)(于2014年9月星期二通过补丁程序发送到所有Windows计算机)将ASP.NET 设置为忽略EbableViewStateMac设置。
开启签名以后得生成viewstate的大致步骤
(1)页面和所有参与控件的状态被收集到状态图对象中。
(2)状态图被序列化为二进制格式
a. 密钥值将附加到序列化的字节数组中。
b. 为新的序列化字节数组计算一个密码哈希。
c. 哈希将附加到序列化字节数组的末尾。
(3) 序列化的字节数组被编码为base-64字符串。
(4)base-64字符串将写入页面中的__VIEWSTATE表单值。
web.config 中关于ViewState 的配置
ASP.NET 通过web.config 来完成对网站的配置。下面来看一些关于viewstate的常见配置:
<pages enableViewState="false" enableViewStateMac="false" viewStateEncryptionMode="Always" />
1)enableViewState:开启或者关闭ViewState
enableViewState:用于设置是否开启viewState,但是请注意,根据 安全通告KB2905247 中所说,即使在web.config中将enableViewState 设置为false,ASP.NET服务器也始终被动解析 ViewState。也就是说,该选项可以影响ViewState的生成,但是不影响ViewState的被动解析。实际上,viewStateEncryptionMode也有类似的特点。
2)enableViewStateMac:是否开启viewState Mac(校验)功能
enableViewStateMac:用于设置是否开启ViewState Mac (校验)功能。在 安全通告KB2905247 之前,也就是4.5.2之前,该选项为false,可以禁止Mac校验功能。但是在4.5.2之后,强制开启ViewState Mac 校验功能,因为禁用该选项会带来严重的安全问题。不过我们仍然可以通过配置注册表或者在web.config 里添加危险设置的方式来禁用Mac校验。
3)viewStateEncryptionMode:是否开启ViewState Encrypt (加密)功能
viewStateEncryptionMode:用于设置是否开启ViewState Encrypt (加密)功能。该选项的值有三种选择:Always、Auto、Never。
•Always表示ViewState始终加密;
•Auto表示 如果控件通过调用 RegisterRequiresViewStateEncryption() 方法请求加密,则视图状态信息将被加密,这是默认值;
•Never表示 即使控件请求了视图状态信息,也永远不会对其进行加密。
在实际调试中发现,viewSta