本章会简要阐释对用户而言操纵HTTP请求(例如,修改cookies,隐藏或禁用表单字段等)是多么容易的事情,这会让我们在正确的思维框架下清楚地考虑web的安全性。接着会依次介绍常见的避免攻击的指南,并了解它们的工作原理以及它们怎么应用到MVC框架里面。还会描述如果阻止每一种攻击的形式或者是更换的并设计出来。
所有的输入都是可以被伪造的(All Input Can Be Forged)
有这样一句话:不要相信用户的输入。用户的输入有哪些种类呢?如下所示:
①传入的URLs(包括Request.QueryString[]的值)
②表单提交的值(Request.Form[]的值,包括隐藏域和禁用的字段值)
③Cookies
④Http报头的值(例如Request.UserAgent和Request.UrlReferrer)
基本上,用户的输入包括Http请求的全部内容。这不是让我们停止使用cookies或querystring的意思,而是让我们明白在设计应用程序的时候,不要天真的以为用户不可能操纵cookie或隐藏表单的值。
HTTP的工作原理(HOW DOES HTTP WORK?)
1.简单的Get请求
当浏览器发起一个URL请求如,浏览器会对域名执行DNS查找,并在这个IP地址的80端口上打开一个TCP连接并发送如下数据:
GET /path/resource HTTP/1.1
Host:
[空行]
也有一些额外的报头,但这是所有严格要求的。web服务器响应以下内容:
HTTP/1.1 200 OK
Date: Wed, 31 Mar 2010 14:39:58 GMT
Server: Microsoft-IIS/6.0
Content-Type: text/plain; charset=utf-8
<HTML>
<BODY>
I say, this is a <i>fine</i> web page.
</BODY>
</HTML>
2.带cookies的Post请求
Post请求也不是非常复杂,主要的不同是它能够在HTTP报头之后包括一些发送的负荷内容。下面的例子中包含常见的HTTP报头:
POST /path/resource HTTP/1.1
Host:
User-Agent: Mozilla/5.0 Firefox/2.0.0.12
Accept: text/xml,application/xml,*/*;q=0.5
Content-Type: application/x-www-form-urlencoded
Referer:
Content-Length: 45
Cookie: Cookie1=FirstValue; Cookie2=SecondValue
firstFormField=value1&secondFormField=value2
这些负荷内容是一套键值对,通常是代表了一个form里面的所有input控件。cookies也是在一个单独的HTTP报头里面作为通过分号分隔的一序列键值对传输。注意:我们不能严格的控制cookie的过期时间,可以设置一个期望的时间,但是不能强迫浏览器一定会满足我们的期望。
伪造HTTP请求(Forging HTTP Requests)
最基本,最低级的发送一个随意的HTTP请求的方式是使用DOS控制程序telnet代替web浏览器。打开一个命令行对话框,输入telnet 80.这种方式表明任何人都可以发给服务器任何报头和cookie的值。(win7默认没有安装telnet客户端,可以在控制面板→程序和功能→打开/关闭windows功能→Telnet客户端)(这里我测试没返回HTML结果,不知道是什么原因 )
然后如果手动的去键入整个HTTP请求而不犯错会有困难,更加容易的方式是截取一个实际的web请求然后修改它。Fiddler就是这样一个能够记录所有客户端和服务器间的http请求,允许你监视,设置断点,甚至修改输入输出数据,它作为一个本地的web代理的工具,浏览器通过它发送请求而不是直接到Internet。举个例子,可能有网站层使用cookie来存放用户的角色,定一个IsAdmin的cookie(值为true/false),这时我们就可以改变cookie的值然后发送实际的请求。我试过用Fiddler来改变cookie的值但是右键没有编辑的选项,可能是我不会用Fiddler的原因吧,知道的童鞋请留言告诉我,谢谢。这里我直接截取书中的图给大家看下:
类似的,我们可以编辑Post的数据绕过客户端验证或者发送一个假的Request.UrlReferrer信息。除非我们可疑的对待每一个HTTP请求,否则就让一些恶意的或者好奇的访问者更加容易的访问网站的数据或通过修改querystring,form,cookie数据来执行没有授权的action。解决这个问题的方案不是组织请求操纵或者期望ASP.NET MVC来为我们处理,而是检查接收的每一个登录的用户的请求是否合法。
跨站点脚本和HTML注入(Cross-Site Scripting and HTML Injection)
一种更加阴险的攻击策略是强迫不知情的第三方浏览器发送代表了攻击者的HTTP请求,滥用在应用程序和受害者之间已经确立的身份关系。。原理非常简单:如果一个攻击者得到我们的站点并返回一些随意的js给访问者,那么攻击者的脚本就能够控制访问者的浏览会话,并可能动态的修改HTML DOM让我们页面受损,比如注入不同的内容,像弹出一个兑奖窗口什么的,或者将访问者导向了其他站点。还或者利用用户对我们域名或品牌的信任诱导或强制用户安装他们的软件。
跨站的关键是攻击者利用我们的服务器返回他们的脚本给访问者,那么脚本就可以运行在我们域名这样一个安排的背景下。攻击者有两种实现的方式:
1.持久的:在网站的一些交互功能区,如留言板。输入恶意的内容,并且期望于我们会将这些内容存入数据库并呈现给其他的访问者。
2.非持久的或被动的:通过找到一种在请求里发送恶意数据的方法并且让应用程序仿效发送的数据进行响应,然后攻击者会找到一种方式来欺骗受害者发起这样的请求。
理解一个XSS的漏洞(Understanding an XSS Vulnerability)
在前面SportsStroe示例项目里面,我们添加了一个Index的action并接收一个returnUrl的参数。这个参数会被复制到CartIndexViewModel对象(作为视图模型对象传递给视图)视图使用这个值呈现如下链接:<a href="@Model.ReturnUrl">继续购物</a>。很容易从中看出一个潜在的XSS漏洞,由于响应的部分HTML标签使用了querystring参数的值来生成,攻击者可能会试图提供静心设计returnUrl querystring参数,从而导致结果页包含了恶意脚本。例如攻击者可能诱导用户跟随下面的URL:
?returnUrl="+onmousemove="alert('XSS!')"+style="position: absolute;left:0;top:0;width:100%;height:100%;
可能你觉得上面的URL不足以诱导用户,其实攻击者可以通过一个URL压缩服务隐藏URL并且把它包含在Email里面。很多用户对中奖什么信息非常愿意去打开。