Introducing rkt’s ability to detect privilege escalation attacks on containers
coreos.com
coreos.com
>This state can then be verified whenever a process performs an action requiring a permissions check. For example, when a process requests that a file be opened, the kernel now calls out to the hypervisor. The hypervisor is then able to examine the process state and ensure that it remains consistent with its internal representation of process state.
Makes me very uneasy. You're making the hypervisor more complicated, duplicating the logic in the kernel, because you feel the kernel is insecure. The only argument for doing this, AFAIK, is that the hypervisor is still simpler overall, and therefore more secure. But when you start introducing these kind of complications, that argument becomes kind of farcical... Adding another layer on top of the kernel and duplicating your permissions checks in there, I do not think that will end well.
The argument for this isn't that the hypervisor is simpler, it's that the hypervisor is running at a separate privilege level to the rest of the stack. The hardware enforces an additional level of separation. This just adds validation on the other side of that boundary.
(Disclaimer: author of the code)
If I understand rkt's architecture correctly, the hypervisor runs multiple Linux kernel instances, every kernel runs several processes. If somebody exploits one of those processes and creates a root-owned process, then rkt detects such an attempt and restarts the kernel. But what if the exploit doesn't create any root-owned processes? You can get rights equal to those of the superuser without getting uid=0.
And it's impossible for an exploit to do because?..
EDIT: "?.." in this case means "please continue my sentence".
> Kernel code is mapped read only
What part of the system makes sure that read-only kernel code stays read-only? Is it hardware or the hypervisor?
Another question. Is there any chance that you missed something and there's a way to get privilleged access without actually modifying your uid, bumping your capabilities or modifying kernel code?
And the only way to make the page writable again is to clear the page first. Am I correct?
> You can avoid all of these protections if you can inject new code into an existing privileged process or SUID executable, which is how DirtyCOW worked.
It can happen if either one of these is true: 1) the existing privileged process or SUID executable is vulnerable; 2) the kernel is vulnerable. DirtyCOW is interesting because it's the case #2. The case #1 is not that interesting, because targeting vulnerable privileged executables is a known attack vector.
[1] http://www.gabesvirtualworld.com/vmsafe-what-is-it-exactly/
We are really enjoying using Ceph under rkt-fly[1] upon CoreOS though.
[1] https://coreos.com/rkt/docs/latest/running-fly-stage1.html
[1] http://blablatech.com/blog/why-and-how-blablacar-went-full-c...
And a blog post on their site: http://blablatech.com/blog/why-and-how-blablacar-went-full-c...
That would avoid the weird special case for SUID binaries, which looks like the sort of thing that someone is going to discover an attack on in a year or two. (And it's a special case in lots of systems, not just this one.)
Polkit, incidentally, is another good reason to avoid all SUID binaries on your system; see CVE-2011-1485 and then CVE-2013-4288 and friends, which are all race conditions involving tricking polkit into thinking that you're root by execing a SUID binary right before it checks who you are. http://seclists.org/oss-sec/2013/q3/624
This is indisputably a security bug in polkit, but the fact that it's so non-obvious how to do the right thing (and whether the right thing is even possible) is a good reason not to tempt fate by having SUID binaries around. It's not going to be the only system that's vulnerable to this.
Those listed examples could also be could be achieved with IPC to a privileged daemon. But unfortunately not all setuid executables can be replaced that way.
The major design flaw with setuid executables is that they run in an execution environment (view of the root filesystem, Linux namespace, etc.) provided by the caller. A good explanation of this is http://maxsi.org/blog/setuid-bit-considered-harmful/
Unfortunately this is why not all setuid executables can be replaced with IPC. setuid binaries like "nsenter" allow you to run processes with a selective modification to one part of your execution environment, while still inheriting everything else unmodified. You can't achieve this with IPC to a privileged daemon because that daemon cannot inherit your current execution environment when starting new processes.
Nevertheless, getting rid of setuid is very important. Kind of baffling to me that it hasn't been done yet. The closest we've come is replacing setuid with filesystem capabilities, but those have the same fundamental design problem. I've been working on genuinely getting rid of setuid some myself. Happy to collaborate with anyone else who wants to work on this.
What if it could? An "execution environment" could be turned into some sort of kernel token object that could be passed to another process over IPC. A privileged daemon could receive one, fork(2) once, drop some privileges, and then fork(2) again, this time with the execution-environment parameter—and end up with a copy of itself running under the IPC-sender, with environment inherited from the sender but privileges inherited from the receiver (and, presumably, an address space that contains all the mappings of both parents, with the IP pointing into the receiver's code section, like a normal fork(2) would.)
One way you could do this is to heavily abuse the CRIU project. https://criu.org/Main_Page Just do the following:
1. fork
2. send a request to a privileged daemon
3. privileged daemon checkpoints your child
4. privileged daemon modifies the saved state of your child in whatever way you requested
5. privileged daemon resurrects your child (which is possible because it is privileged)
I am not really serious about this method but it is certainly a thing you could do. :)
https://lwn.net/Articles/632520/
Having CAP_SYS_ADMIN is effectively the same as running as root.
If you have some mitigation techniques available, you will be able to block many attacks while providing a good guideline what your software does not do and encourage "white hacks" to come up with better mitigations.
(disclaimer: author of this feature)
https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Pr...
https://lwn.net/Articles/698827/ (note the admission in the comments by all sides that KSPP is essentially about upstreaming all the upstreamable ideas in grsecurity, to bypass the sort of yelling that you see in those comments)
The trouble is that the incompatible ideas run contrary to Linux's philosophy of compatibility / "don't break userspace" being the highest virtue, but that at least isn't about personalities, just differing design goals.
Fast forward to now and you have kernel heavyweights like Kees Cook (former Canonical kernel/security lead now chromeos security badass extraordinaire) working on bringing these features into mainline via the aforementioned KSP projects. In the end, Linux is getting more secure, and it is largely in part to the hard work of the entire GRSec team, even if they're a bit abrasive to work with.
>The apparent inability (and perhaps more importantly - total unwillingless) from the PaX team to be able to see what makes sense in a long-term general kernel and what does not, and split things up and try to push the sensible things up (and know which things are too ugly or too specialized to make sense), caused many PaX features to never be merged.
Although there are other posts since debating the same point such as this one https://lkml.org/lkml/2005/1/25/141