Live data from Hacker News

Unikernels are secure

unikernel.org

131–140 of 142 posts

Re: Unikernels are secure

#131
post #120
post #119

Earlier quoted context omitted.

Access to ring 0 on a traditional OS is indeed usually "game over". In the case of a unikernel deployed on a hypervisor this is not the case, since there is not much else in ring 0 that you wouldn't already have access to from ring 3. Conceptually you can think of the hypervisor as "kernel space" and anything inside the unikernel as "userspace". There are advantages to running the unikernel solely in ring 3 (eg. immu…

I still see it as worse than a normal application being compromised. When Ring 0 is compromised, there is no alert or anything to protect the app from compromise. If there is an exploit, it's game over. However, in Ring 3 and a normal kernel, you get various protections that allow the kernel to recognize some attacks and shutdown the application immediately or even shutdown the kernel. This prevents a compromised app…

> A unikernel cannot do this. If the app is compromised and I don't notice and don't restart it...

I disagree. There's no reason such mitigations (not sure what exactly you're referring to) can't be implemented by the monitor process (ukvm in the Solo5/ukvm model).

I'd also argue that a normal kernel does not do any integrity checks on the code running in a user process, so the model is exactly the same.

> Even worse, the attacker could use it as leverage to infect other unikernel based instances of the app to gain some permanence against restarts by simply reinfecting when an instance goes down.

For that they'd need to break out of the virtual machine and into the hypervisor / monitor. Which is by no means impossible, but with careful design of unikernel-specific monitors can be much reduced. Of course, I'm by no means suggesting you should back your unikernels with a monitor along the lines of QEMU :-)

Re: Unikernels are secure

#132
post #131
post #120

Earlier quoted context omitted.

I still see it as worse than a normal application being compromised. When Ring 0 is compromised, there is no alert or anything to protect the app from compromise. If there is an exploit, it's game over. However, in Ring 3 and a normal kernel, you get various protections that allow the kernel to recognize some attacks and shutdown the application immediately or even shutdown the kernel. This prevents a compromised app…

> A unikernel cannot do this. If the app is compromised and I don't notice and don't restart it... I disagree. There's no reason such mitigations (not sure what exactly you're referring to) can't be implemented by the monitor process (ukvm in the Solo5/ukvm model). I'd also argue that a normal kernel does not do any integrity checks on the code running in a user process, so the model is exactly the same. > Even worse…

1) You are in Ring 0. There is no defense unless you reimplement a normal Kernel to run a process in Ring 3 along with the monitoring process and capabilities management... etc

2) No, the attacker is most likely there because of some bug in the app, once in the network, it becomes harder to stop the attacker infecting other instances.

3) Hypervisors are not perfect. There are known instances of people infecting the host through the hypervisor.

Re: Unikernels are secure

#133

Earlier quoted context omitted.

I have no idea, but couldn't you use some part of the software you just compromised that makes syscalls?

There are no syscalls as the fine article explains.

Ah, wait, I mis-read your comment and it's too late to edit mine. Yes, that sounds plausible, and particularly if you have the source code, which you do for many common servers.

Re: Unikernels are secure

#134
post #118
post #35

Earlier quoted context omitted.

And, while this is a more minor rebuttal, it's still worth saying: it's totally incorrect . Modern exploits (for definitions of "modern" meaning "written after 1999") do not care if you have a shell on your system. The author has presumably confused the concept of a POC, which is an exploit reduced and simplified for the consumption and understanding of laypeople, with that of a real exploit.

As one the early users[1] guilty of using the "there is no shell" argument for unikernel security, I agree with what you say. I would rephrase the argument as "there is no fork()/exec()", meaning that a unikernel cannot spawn a new process. A unikernel application which only executes native code[2], combined with a hypervisor / hardware that enforces immutable page tables and NX, AFAICT leaves ROP/JOP as the sole rem…

If you want to prevent fork/exec, that's super easy to do in a conventional Linux application:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
    struct sock_filter filter[] = {
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, arch)),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_fork, 4, 0),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_vfork, 3, 0),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_clone, 2, 0),
        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 1, 0),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
    };
    struct sock_fprog fprog = {
        .len = sizeof(filter) / sizeof(filter[0]),
        .filter = filter,
    };
    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &fprog, 0, 0);
or, if you're using systemd, simply

    SystemCallFilter=~fork,vfork,clone,execve
Again, the hard part here is architecting your application not to need fork/exec for its own purposes anyway, which (as far as I'm aware) is a strict prerequisite of porting it to the unikernel model. If you can do that, forswearing fork/exec for security purposes is straightforward and doesn't require a unikernel. (Also, if you take the prctl approach, you can do that after you've forked a few helper processes, which is probably a much easier port!)

Or in other words, the argument isn't "unikernels are secure," it is "programming in an environment without fork/exec is secure," and unikernels are a needlessly complicated way to provide that environment.

Re: Unikernels are secure

#135
post #132
post #131

Earlier quoted context omitted.

> A unikernel cannot do this. If the app is compromised and I don't notice and don't restart it... I disagree. There's no reason such mitigations (not sure what exactly you're referring to) can't be implemented by the monitor process (ukvm in the Solo5/ukvm model). I'd also argue that a normal kernel does not do any integrity checks on the code running in a user process, so the model is exactly the same. > Even worse…

1) You are in Ring 0 . There is no defense unless you reimplement a normal Kernel to run a process in Ring 3 along with the monitoring process and capabilities management... etc 2) No, the attacker is most likely there because of some bug in the app, once in the network, it becomes harder to stop the attacker infecting other instances. 3) Hypervisors are not perfect. There are known instances of people infecting the…

1) Virtualized Ring 0 != Ring 0. See section 24.6 "VM-execution control fields" of the Intel SDM for details of the controls a hypervisor can use to modify guest behaviour.

2) The same applies to any application, not just unikernels.

3) I completely agree.

Re: Unikernels are secure

#136
post #134
post #118

Earlier quoted context omitted.

As one the early users[1] guilty of using the "there is no shell" argument for unikernel security, I agree with what you say. I would rephrase the argument as "there is no fork()/exec()", meaning that a unikernel cannot spawn a new process. A unikernel application which only executes native code[2], combined with a hypervisor / hardware that enforces immutable page tables and NX, AFAICT leaves ROP/JOP as the sole rem…

If you want to prevent fork/exec, that's super easy to do in a conventional Linux application: #include #include #include #include #include #include prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); struct sock_filter filter[] = { BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, arch)), BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0), BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), BPF_STMT(BPF_LD | B…

> If you want to prevent fork/exec, that's super easy to do in a conventional Linux application:

And mmap(), mprotect(), ptrace(), ..., $syscall_du_jour(). It's not about fork/exec, it's about limiting the APIs available to the unikernel by default and by design.

Yes, you can do this for conventional Linux applications. But I wouldn't call it super easy, at least not for the vast majority of developers out there.

Re: Unikernels are secure

#137
post #135
post #132

Earlier quoted context omitted.

1) You are in Ring 0 . There is no defense unless you reimplement a normal Kernel to run a process in Ring 3 along with the monitoring process and capabilities management... etc 2) No, the attacker is most likely there because of some bug in the app, once in the network, it becomes harder to stop the attacker infecting other instances. 3) Hypervisors are not perfect. There are known instances of people infecting the…

1) Virtualized Ring 0 != Ring 0. See section 24.6 "VM-execution control fields" of the Intel SDM for details of the controls a hypervisor can use to modify guest behaviour. 2) The same applies to any application, not just unikernels. 3) I completely agree.

1) You are still on a Ring 0. On a normal operating system, an exploited app has a limited action range, depending on the system settings. A lot of exploits simply do not work because the operating system kills the process. On Ring 0, even virtualized, all these protections do not work. You have full control within the VM and you can't have some process within the VM to check this as it is equally vulnerable.

2) Yes but Unikernels do not provide special protection against this either.

Re: Unikernels are secure

#138
post #137
post #135

Earlier quoted context omitted.

1) Virtualized Ring 0 != Ring 0. See section 24.6 "VM-execution control fields" of the Intel SDM for details of the controls a hypervisor can use to modify guest behaviour. 2) The same applies to any application, not just unikernels. 3) I completely agree.

1) You are still on a Ring 0. On a normal operating system, an exploited app has a limited action range, depending on the system settings. A lot of exploits simply do not work because the operating system kills the process. On Ring 0, even virtualized, all these protections do not work. You have full control within the VM and you can't have some process within the VM to check this as it is equally vulnerable. 2) Yes…

> On a normal operating system, an exploited app has a limited action range

Minor point, but this seems to be a bit lost in the discussion: Generally 1 unikernel == 1 VM (or, virtualization-backed sandbox, the use of "virtual machine" brings too much baggage with it) == 1 application.

So, the attack scope for the class of attacks we're debating is equally limited to a single application, just like on a normal operating system.

Re: Unikernels are secure

#139
post #138
post #137

Earlier quoted context omitted.

1) You are still on a Ring 0. On a normal operating system, an exploited app has a limited action range, depending on the system settings. A lot of exploits simply do not work because the operating system kills the process. On Ring 0, even virtualized, all these protections do not work. You have full control within the VM and you can't have some process within the VM to check this as it is equally vulnerable. 2) Yes…

> On a normal operating system, an exploited app has a limited action range Minor point, but this seems to be a bit lost in the discussion: Generally 1 unikernel == 1 VM (or, virtualization-backed sandbox, the use of "virtual machine" brings too much baggage with it) == 1 application. So, the attack scope for the class of attacks we're debating is equally limited to a single application, just like on a normal operati…

Not quite.

When you write an exploit for a normal operating system application, you can't, for example, just write your payload into data memory and start executing it. You can't jump to the address of an array and have the CPU execute it's contents.

On a unikernel this sort of thing becomes trivial since everything is Ring 0 and all protections can be trivially disabled.

You can just write your payload into any arbitrary data field and your exploit only needs to jump to it, even with address randomization this can be exploited (ASLR and similar techniques do not prevent exploits, only make them harder)

The exploiting just becomes a whole lot easier.

It's not even remotely more secure than Ring 3 code running on a kernel that has strict capability enforcement.

Re: Unikernels are secure

#140
post #139
post #138

Earlier quoted context omitted.

> On a normal operating system, an exploited app has a limited action range Minor point, but this seems to be a bit lost in the discussion: Generally 1 unikernel == 1 VM (or, virtualization-backed sandbox, the use of "virtual machine" brings too much baggage with it) == 1 application. So, the attack scope for the class of attacks we're debating is equally limited to a single application, just like on a normal operati…

Not quite. When you write an exploit for a normal operating system application, you can't, for example, just write your payload into data memory and start executing it. You can't jump to the address of an array and have the CPU execute it's contents. On a unikernel this sort of thing becomes trivial since everything is Ring 0 and all protections can be trivially disabled. You can just write your payload into any arbi…

> On a unikernel this sort of thing becomes trivial since everything is Ring 0 and all protections can be trivially disabled.

If the hypervisor sets the relevant VMCS control fields for the unikernel to cause a VMEXIT on (for example) a load of CR3 and any EPT violations and sets up the guest with a static set of read-only and executable (or in fact, with EPT you could even do execute-only) pages then there is no way the unikernel can disable these protections.

Having said that, I'm not arguing that running unikernels in Ring 0 is the best approach for security, just that it's not impossibly insecure.

With ukvm we're also looking into running all of the unikernel in (virtualized) Ring 3 with nothing running in Ring 0. However, this needs more experimentation since with x86 you can't (for example) easily handle legitimate exceptions (e.g. divide by zero) from Ring 3.

Post reply on HN