JSON劫持以及ASP.NET

来源:互联网 发布:java web listview 编辑:程序博客网 时间:2024/06/05 04:41

摘自Scott Guthrie 的博客

最近,由安全研究人员发表的一些报告描述了一些方法,可以被黑客通过利用为绝大多数流行的AJAX框架所用的JSON线上格式来试着利用(exploit)浏览器中的跨域脚本。具体来说,这些攻击使用通过 HTML <script src=""> 包含(include)元素来调用的HTTP GET请求来绕过由浏览器强制执行的同源策略(same origin policy)”(同源策略限制了象XmlHttpRequest这样的JavaScript对象只能调用当前页面来自的同一域上的URL),然后寻找利用(exploit)JSON负载内容的方法。

ASP.NET AJAX 1.0 包括了许多默认设置和内置特性,可以防范它免受这些类型的JSON劫持攻击。下面是它如何缓和这些攻击的一些细节:

ASP.NET AJAX Web方法在默认情形下是禁止HTTP GET请求的

通过浏览器中的HTML <script src=""> 元素来装载的脚本文件只能通过HTTP GET动词请求来获取。

在默认情形下, ASP.NET AJAXweb服务层不允许web方法通过HTTP GET 动词来调用。譬如,假如一个开发人员编写了象下面这样的web服务方法:

[WebMethod]
public StockQuote[] GetQuotes(string symbol) {

}

ASP.NET只允许上面的GetQuotes方法通过HTTP POST动词来调用,会拒绝通过HTTP GET动词调用该方法的任何尝试。

要使一个ASP.NET AJAX web方法可以通过HTTP GET来访问,开发人员必须明确地使用ASP.NETScriptMethod 特性来标记每个web方法(同时设置UseHttpGet属性为true):

[WebMethod] 
[ScriptMethod(UseHttpGet
=true)] 

public StockQuote[] GetQuotes(string symbol) { 

虽然这类改动很容易做,但它要求一个开发人员有意识地启用web服务的GET调用。ASP.NET AJAX web服务绝不会故意地启用GETASP.NET AJAX文档明确地指出了许多理由(URL篡改的危险是其中一个理由),不赞成启用GET来调用web服务端点

注: ASP.NET AJAX UpdatePanel 控件,以及随ASP.NET AJAX 1.0一起发布的其他服务器控件,在做异步postback时,并不使用HTTP GET,而是使用HTTP POST

ASP.NET AJAX Content-Type 头信息的验证

我们有一个由ASP.NET强制执行的针对基于GETPOSTASP.NET AJAX web方法的内置的验证保护层,不管用了哪个HTTP动词,ASP.NET总是要求HTTP Content-Type头信息是被设置为 application/json 这个值的。假如这个content type头信息并没有被发送过来,那么ASP.NET AJAX就会在服务器端拒绝这个请求。

用前面的股票报价方法的例子,一个ASP.NET AJAX GET调用的跟踪输出必须看上去象下面这样:

GET /StockService/Stock.asmx/GetQuotes?symbol=%22msft%22 HTTP/1.1 
Accept: */* 
Accept-Language: en-us,fr;q=0.5 
Referer: http://xxxxxx/StockService/test.aspx 
Content-Type: 
application/json; charset=utf-8 
UA-CPU: x86 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; 
.NET CLR 2.0.50727; InfoPath.2) 
Host: xxxxxx 
Proxy-Connection: Keep-Alive 

注意,即使上面只是个GET请求,客户端ASP.NET AJAX JSON层还是会插入一个Content-Type HTTP头的,告诉服务器把这个请求当作是个AJAX web服务请求。ASP.NET AJAX 1.0的服务器端web服务层总是检查这个特定的content type,如果没找到的话,它就会拒绝这个请求。

假如一个恶意的开发人员对这个web服务使用HTTP GET来尝试跨站请求伪造攻击时,他们也许会在他们的网页里包括一个象下面这样的脚本标识:

<script type="text/javascript" src="http://contoso.com/StockService/Stock.asmx/GetQuotes?symbol=msft" /> 

但是,浏览器在分析<script src="">元素,发送请求时,是不会 Content-Type 设置成application/json的。结果是,ASP.NET 将接收到一个来自 <script />包含的请求,但它不会将其认为是对ASP.NET AJAX web服务的一个请求,这会造成一个ASP.NET错误,声明它不认识被请求的URL。这就会避免JSON劫持尝试(即使你有一个允许GET动词调用的web方法)。

结语

在默认情形下,在使用JSON调用web方法时,ASP.NET AJAX 1.0只允许使用HTTP POST动词,这意味着你不会无意中允许浏览器通过HTTP GET来调用方法。

ASP.NET AJAX 1.0 要求在通过GETPOST调用AJAX web服务时,Content-Type头被设置成“application/json” 不包含这个头信息的JSON请求会被ASP.NET服务器所拒绝。这意味着,你不能通过<script src=""> 包含(include)来调用ASP.NET AJAX web方法,因为在象这样请求JavaScript文件时,浏览器不允许附加自定义的content-type头信息。