This is a paper I wrote ages back, forgot about, decided to publish after OpenSSL got popped, forgot about *again* because my site was being a bollix and not working, and then remembered when walking home today. For the /r/netsec folk who will probably bash it as lame/not a new idea, yeah, its not new. Its not even that cool. But I still found it amusing as it helps show that “Virtual Private Servers” are not exactly anything that could be called private.
This paper documents a trivial method of injecting code with superuser privileges in guest virtual machines on OpenVZ systems. The conditions are that you have access to the host machine, with either a superuser account or one which has access to the OpenVZ virtual machines process space, for example, the SolusVM account on badly configured SolusVM setups. Such setups are rather common in the wild in both enterprise settings (private clouds) and VPS/web hosting companies. While not providing a remote-root exploit, it is an interesting method of abusing shared processes in virtualization software to own boxes.
Recently I, the author, was granted access to an OpenVZ setup on a virtual server host by the owner, and permitted to use it for experimentation purposes with the view to iron out any bugs before the service was publicly launched. The setup was using SolusVM/WHMCS to “Manage” the VPS servers and customer service, on an x86_64 CentOS host. The virtualization software was the reasonably popular OpenVZ software.
Previously, the author had worked with a colleague on a Linux process-injection tool, beta testing it and locating bugs. It was realized, after reading the (terrible) OpenVZ documentation, and after an idiot administrator ran “killall apache2” on the main host, that in an OpenVZ setup the process space is shared, with the processes on guest operating systems being directly accessible from the host machine.
The natural line of investigation from this was “what will happen if we try inject code into the processes of virtual machines running on the host, from the host itself?”. This line of investigation lead to the following vulnerability being discovered, and exploitation was found to be incredibly reliable.
General Overview of Exploitation:
From the host machine, all the guest systems processes run in a shared space, and may be directly manipulated from the host operating system. For example, running “killall apache2” on the host system will send the kill signal to any Apache2 processes running on the host systems (generally leading to pissed off customers). I believe this architecture is designed so a host can legitimately terminate processes on guest systems which are consuming more than their allocated amount of resources.
Seeing as the process space of guest systems is directly accessible to the host, standard techniques for process injection may be used to execute code on any or all of the guest operating systems. Therefore, it is considered trivial to inject code into guest operating systems from the virtual machine host while using the OpenVZ virtualization solution.
Impact of Exploitation:
While some may think that “if the host is rooted, the guests are compromised anyway”, and simply ignore the content of this paper, there are several rather interesting ramifications to this technique. They are not wrong either.
Of primary interest, it demonstrates that there can be no real expectation of privacy for users of “Virtual Private Servers”, which include many web hosting firms and enterprises.
It also demonstrates the lack of protection of guest processes from the host in the OpenVZ stack, which means the guests not only have to worry about the security of their own server, but are completely at risk if the host machine is compromised. Finally, it was a really neat trick, and allowed for some interesting things to be done.
For this demonstration, we used the process-injection tool developed by “jtRIPper”, “parasite”. You may download it from: https://github.com/jtRIPper/parasite
The host machine was running CentOS, OpenVZ and SolusVM (management software for OpenVZ). The guest host used in this demonstration, “bastion”, was running Debian. All architectures are x86_64. The utilities used on the hosting server were the “vzlist” utility, grep, and the “ps” tool, for location of process ID’s to inject into.
Exploitation, step by step:
Step one: use “vzlist” to find the CTID of the target virtual machine. The CTID is the number, normally a three digit number, listed in the first column. In the screencap, I told it to only output the details of my target virtual machine using grep. It also will give you the IP address of the target machine, take note of this as we will use it to connect to the bind-shell later.
Step two: Once you have the CTID of your target virtual machine, simply running “ps aux | grep $(CTID)” (put your CTID in there…) will list running processes on the target virtual machine. It will also output some unrelated processes, but the owner of the processes will be the same as the CTID, making locating them easy. A cleaner way is to grep for “root/$(CTID)” which I did in the demo to make it cleaner output.
Step Three: Process ID in hand, we use the parasite utility to inject our shellcode into the process. The payload is a bindshell on port 4444. Simply do “./parasite $(PID)” to inject code.
Step Four: Use netcat to connect to the bindshell on port 4444 of the target host. You should have the privileges of the process you injected into.
Step Five: Well, thats the box rooted, so, er, have fun and play safe?
This technique can be used to gain access to virtual machines from
the host machine. This impacts the integrity and privacy of the data
on the virtual machine.
It also provides an interesting lesson in how Linux process injection
techniques can be used to do more interesting things than simply
backdooring the SSHd on the host.
This proves conclusively that under OpenVZ, the guest virtual
machines are completely vulnerable to the host VM. This has
definate ramifications for the supposed privacy of “Virtual Private
Servers” on an OpenVZ stack, as it means the percieved privacy
may be completely subverted by a rogue administrator.
There is a lack of seperation of processes in the OpenVZ
hypervisior, which can be abused by someone with access to the
host machine to execute code inside the guest virtual machines.
This can allow the host to subvert any security restrictions or similar
on running guest machines, allowing theft of potentially confidential
data from clients on the guest VM’s.
If you are using a VPS server which is on an OpenVZ stack, you
therefore have no expectation of privacy whatsoever from the host
Other hypervisiors have been shown to be similarly exploitable in
the past, for example VMware. Further research into XEN and
Virtualbox/KVM hypervisiors shall be needed to see if those also can
be exploited (they can ).
Code and further information/ideas:
https://github.com/jtRIPper/parasite – Process injection tool used in
http://cymothoa.sourceforge.net – Potentially useful Process
https://github.com/batistam/VMInjector – VMware Host to Guest
Code Injection PoC for Windows.
http://openvz.org/Processes_scope_and_visibility – Information on
processes in the OpenVZ hypervisior and ideas on making a better
OpenVZ also allows filesystem access from the host, no protection
whatsoever against a malicious superuser on the host
reading/altering your files. Apparently, a superuser on host can also
spawn processes and suchlike, but the OpenVZ documentation was
so rubbish, and I did not have the patience to find out/verify.
A guest-host jailbreak is doable on OpenVZ via kernel exploits, as
seen with Enlightenment breaking out of OpenVZ containers, which
are just a glorified chroot. As I no longer have access to
infrastructure on which to run further testing (as of Feb. 2014), I
cannot do further research until further notice. Unless, of course,
someone wishes to just give me a dedicated server and a bunch of
IP addresses to do with as I please