Introduction

As part of his master thesis Leonard Rapp analyzed the security of various popular unikernels.
The first two blog post discussing the results of an in-depth analysis of the research unikernel RustyHermit can be found here and here. The blog post giving an overview of a basic analysis of the popular unikernels OSv, nanos, Unikraft and Mini-OS is published here.
Leonard also did a presentation of his work at GPN20, a recording of the talk is published on media.ccc.de.
This blogpost is the last one in the unikernel series. It discusses some of the findings and draws a conclusion.

The basic idea of unikernels is to compile a library operating system together with an application into a single purpose and single address space image which can be run on a hypervisor. This approach is much more lightweight in terms of code size, startup time and performance than a traditional operating system.
Multiple unikernels claim to have a high grade of security or to be even more secure than Linux.

Discussion

Using Rust for Unikernel Development

One of the main motivations for this thesis is to contribute an analysis of a unikernel written in a memory safe language. Thus, an in-depth analysis of RustyHermit was conducted, the results were presented in previous blogposts.
Writing a unikernel in Rust has the benefit that memory corruption vulnerabilities can only occur in unsafe code parts. This significantly reduces the impact for code audits when looking for memory corruption vulnerabilities. Thus, it was possible to review every single line of unsafe code, which would not have been possible with a unikernel written in e.g.\ C.
However, the unsafe code parts might still contain memory corruption vulnerabilities. They are necessary for various tasks in operation systems, e.g.\ for direct memory access in device drivers. A good showcase is the out-of-bounds read vulnerability in RustyHermit’s rtl8139 network card driver, presented in a previous blogpost.
While the kernel / libOS is written in a memory safe language, the application might still be written in an unsafe language. For example RustyHermit allows applications to be written in C.
Thus, writing a unikernel in Rust is a great and important approach to increases security, but one should be aware that this does not prevent every memory corruption vulnerability.

Unikernel Security Claims

A major claim of unikernels is that they are more secure due to the massively reduced attack surface because of the libOS approach. This is surely true as a only the code is compiled into the resulting image that is necessary for fulfilling the single purpose it was created for. This leads to less code used and code which is not there can not contain exploitable vulnerabilities.
However, the application might be arbitrarily large and might massively increase the attack surface. Thus, the argument of reduced attack surface is correct, but no replacement for other security measures.
In addition, the focus on lightweightness and performance seems to lead to unikernel developers leaving out the implementation of security mechanisms.

Another major security claim is the isolation introduced by using one unikernel for exactly one application and isolating the unikernels from the host system and each other by the hypervisor. This is a very good additional protection against lateral movement, as an attacker successfully exploiting an application running in a unikernel would not have direct access to other applications. However, this does not provide protection against initially compromising a unikernel. Thus, it can not be a replacement for classical security mitigations.

The single address space is also an inherent property of unikernels and should be kept in mind when discussing unikernel security.
Due to the single address space, an attacker successfully exploiting the application would have full access to every part of the unikernel without the need of additional escalation of privilege exploits. An attacker would have full access to e.g.\ the network stack or the hypercall interface. Thus, it is even more important for unikernels to prevent an attacker from initially exploiting a vulnerable application.

Conclusion

The most important conclusion is that writing a secure unikernel in terms of “no vulnerabilities” is not enough. The kernel developer has no control over an arbitrarily insecure application, but in a unikernel the kernel and the application are compiled into one single image. Thus, the unikernel / libOS developer always has to keep the application in mind and accordingly provide security mitigations to hinder an attacker from successfully exploiting a vulnerable application.
In this series of blogposts it was shown, that many of those mitigations are not implemented at all or fundamentally flawed for various unikernels.

Diclosure

OSv

As there are already GitHub issues discussing ASLR and stack canaries, it is not necessary to open new issues to report this thesis’ findings to the OSv developers. The issues already existing are:

nanos

The findings were reported to the developers via the provided security @ email address.

Unikraft

There already is an open pull request discussing ASLR, thus it was not necessary to open an issue to report missing ASLR:

Mini-OS

As Mini-OS is not developed on GitHub, the issues were reported to the maintainer via email.

About X41 D-SEC GmbH

X41 is an expert provider for application security services. Having extensive industry experience and expertise in the area of information security, a strong core security team of world class security experts enables X41 to perform premium security services.

Fields of expertise in the area of application security are security centered code reviews, binary reverse engineering and vulnerability discovery. Custom research and IT security consulting and support services are core competencies of X41.