Host to Guest Code Injection in OpenVZ

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.

Abstract/Brief:
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.

Introduction:
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.

Practical Exploitation:
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?

injectandown

 

Analysis:
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.

Conclusion:
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
machine.

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
demo.
http://cymothoa.sourceforge.net – Potentially useful Process
Injection tool.
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
process-finding tool.

Addentum:
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 ;)

TinySHell – Ported to SCTP

You may have seen, a while ago, my post on SCTP reverse shells.

I realized quite quickly that I should definately do some more research in this direction, and hence ported one of my favourite Unix backdoors (which uses a TCP connection) to use a SCTP connection instead. This backdoor allows for a remote PTY, file upload, and file download. It also is encrypted connection.

The backdoor in question is ‘TinySHell’ by the inestimable Christophe Devine (who left quite a legacy of code, which I may start to maintain as he appears to have vanished. Chris, if you are out there, get in touch or something! Love your work!). I spent a short while examining the code, then quickly patched it up to replace all the TCP stuff with SCTP stuff. I imagine I could easily alter it to do UDP, and might try that later.

Anyways, without further ado, here is the code. Again, all credit to Chris, all I did was modify it!

https://github.com/infodox/tsh-sctp

Aaaand a video of it in-use (rough cut, no editing, some freezing. Will clean up later)


Also, we have not died here. Some, er, circumstances lead to extended hiatus in publication of research material.

Happy pwning!

[Howto] Installing Nemesis on Ubuntu Linux

Ok. Nemesis is a very powerful Packet Crafting/Injection tool for Unix based systems. I have heard that ALLEGEDLY it can be installed/ran on Windows also, ailment but never felt like trying, as I do not use Windows nor is Windows much good for ANYTHING to do with sockets.

Nemesis is similar to tools like “hping” in that you can customize the packet you want to send, and send it. Very useful for playing with low level protocols, and incredible if you want to learn more about the network layer stuff.

For more information on Nemesis, prostate you can always check out the following links…

http://nemesis.sourceforge.net/

http://www.darknet.org.uk/2007/05/nemesis-packet-injection-suite/

http://packetlife.net/armory/nemesis/

SO. How do I get Nemesis to work on Ubuntu and such?

Well, most distributions do not have it in their repositories it seems, and just because it is easy to do, let’s compile it from source.

Step One: Install Dependancies

First off we need to install the dependancies it has, so the following two commands should do the trick.

apt-get install libdnet-dev
apt-get install libpcap-dev

No screenshot should be needed here I hope…

Step Two: Install “libnet” to the /usr directory.

Now for convenience, I do my installation in the /usr directory. Don’t ask why, it just seemed right at the time.

The following commands should do this easily for you…

The first three are “preparing the build area”

cd /usr
mkdir nembuild
cd nembuild

The next three are “getting the sources and unpacking them”
wget http://ips-builder.googlecode.com/files/libnet-1.0.2a.tar.gz
tar -xf libnet-1.0.2a.tar.gz
cd Libnet-1.0.2a

The next commands “configure” and make + make install the Libnet libraries.
./configure
make && make install

Installing Libnet

So. Now that we have successfully installed Libnet (if you get some wierd errors, leave a comment and I can try help you) we can go on and install Nemesis!

Step Three: Installing Nemesis

So. This is the fun part – where we get to finally install Nemesis.

Assuming you are still in the directory “/usr/nembuild/Libnet-1.0.2a”, just “cd ..”.

Otherwise, “cd /usr/nembuild” so we are all on the same page!

So. Lets prepare our “Environment” for the Nemesis installation by getting and unpacking the sources! The following commands should do it…

wget http://heanet.dl.sourceforge.net/project/nemesis/nemesis/1.4/nemesis-1.4.tar.gz
tar -xf nemesis-1.4.tar.gz
cd nemesis-1.4
Preparing to install Nemesis

So, thats everything prepared. Now for the tricky bit – making it build properly.

Note that I used very specific paths for this – this is because we HAVE to specify THESE libnet libraries!

Now for the next commands…

./configure —with-libnet-includes=/usr/nembuild/Libnet-1.0.2a/include —with-libnet-libraries=/usr/nembuild/Libnet-1.0.2a/lib
make && make install

Done!

Installing Nemesis

There we go! Now for usage and such, “man nemesis” is a good place to start – they don’t make those man pages for nothing you know!

Finally, to wrap up, a screenshot of Nemesis!

Nemesis - Screenshot