I recently switched from KVM / libvirt to Virtualbox for malware analysis due to various reasons. First of all, I was sick of the buggy console output provided by SPICE [1]. I often use IDA running inside of an offline VM, therefore a good quality VM console is important. Virtualbox offers this, apart of some unpleasant things like separate kernel modules, the need for the 'extension pack' if some extended features are wanted and of course it's owned by Oracle...
From a security point of view, the separate kernel modules are an other nasty thing. To make a possible VM escape harder, it makes sense to use some sort of MAC [2] to confine all Virtualbox processes. A focused attacker will anyway try to target directly the kernel and maybe the needed VirtualBox kernel modules.. But an other layer of defense is never wrong ;-)
In this article, I'll show how to create a custom Apparmor profile for Virtualbox.
First we're using aa-genprof to easily generate a basic profile skeleton. aa-genprof will then write a mark to syslog and set the new profile to complain mode. Now the program to profile can be executed and all access attempts will be logged to /var/log/audit.log ( this location actually depends on the used configuration ).
# create basic profile and set to complain mode
aa-genprof -d /etc/apparmor.d /usr/bin/VirtualBox
# execute programm in different shell
/usr/bin/VirtualBox
# scan logs, hit S
The generated draft profile is not really useful at the moment, as it seems not all actions are logged in complain mode. We therefore set the profile to enforce mode:
# set to enforce mode
aa-enforce /usr/lib64/virtualbox/VirtualBox
Now all actions actions are logged and we can use aa-logprof to refine the profile accordingly. aa-logprof will ask you how to handle certain access attempts by the confined program. Such a question may look like this:
Profile: /usr/lib64/virtualbox/VirtualBox
Path: /home/zep/.VirtualBox/selectorwindow.log
Old Mode: r
New Mode: owner rw
Severity: 6
[1 - owner /home/*/.VirtualBox/selectorwindow.log rw,]
2 - owner /home/zep/.VirtualBox/** rw,
3 - owner /home/zep/.VirtualBox/selectorwindow.log rw,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
We can see the used profile (/usr/lib64/virtualbox/VirtualBox) and the denied action, which we can allow now: VirtualBox tried to access the file /home/zep/.VirtualBox/selectorwindow.log. We can now select between 1,2 or 3 to set the access granularity. We can also ignore the event (I), we can deny it explicitly or make the selected path more generic (G). During this event processing we can create also new apparmor profiles for executables, which are started by VirtualBox. At the end we have multiple profiles for VirtualBox, in the best case one profile for each executable. The easiest way to reload the new profile is to restart the apparmor service:
# the generated profiles for VirtualBox
ls /etc/apparmor.d/ | grep VB
usr.lib64.virtualbox.VBoxNetAdpCtl
usr.lib64.virtualbox.VBoxNetDHCP
usr.lib64.virtualbox.VBoxSVC
usr.lib64.virtualbox.VBoxTestOGL
usr.lib64.virtualbox.VBoxXPCOMIPCD
# restart apparmor service to reload all profiles
rc-service apparmor restart
To test the profile, we start again VirtualBox. This will likely fail, because we have not yet executed the entire Virtualbox functionality and therefore the profile is incomplete. But all denied actions are logged and we refine the profile again using aa-logprof. This cycle has to be repeated three to four times.
If we quickly want to disable the profile, we can set it manually to complain mode:
# set to complain mode: only log and don't deny
aa-complain /usr/lib64/virtualbox/VirtualBox
To get a quick overview over all loaded profiles and the status of the confined processes:
# get overview
aa-status
[1] | SPICE: https://www.spice-space.org/ |
[2] | Mandatory Access Control: https://de.wikipedia.org/wiki/Mandatory_Access_Control |