Analysis and Exploitation of a Linux Kernel Vulnerability
perception-point.io
perception-point.io
I don't agree with Torvalds, but at least I can understand him. I don't understand why distros don't implement it.
http://www.washingtonpost.com/sf/business/2015/11/05/net-of-...
Some interesting academic work: http://hmarco.org/data/OnTheEffectivness-NX-SSP-RenewSSP-and...
While SSP is not enough, (use PIE too): http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.ht...
A fun toy: https://github.com/JhetoX/VectorAttackScanner
[1]https://wiki.gentoo.org/wiki/Project:Hardened
[2]https://wiki.gentoo.org/wiki/Hardened/Introduction_to_Harden...
[3]Granted I haven't used it in ages, it's still the benchmark I use in my mind, back when Linux 2.2 was rife with out-of-the-box ROP vulns.
This is all still a work in progress, but expect a blog post once what we have is more polished.
A relatively easy-to-follow blog post was recently published that guides you through building a grsecurity kernel for a Debian desktop installation: [2].
grsecurity was operating a service last year that would allow you to request custom built kernels for a small price, although I can't find it now so it may have been taken offline. This is an ideal solution, and is actually better than packaging the kernels in an distribution's repository, because some of grsecurity's security features are more effective when everybody is running a unique kernel (e.g. RANDSTRUCT).
Finally, the linux-hardening group is working on upstreaming select PaX features into the mainline kernel [3], including PAX_REFCOUNT, which is the protection that would've mitigated this particular vulnerability.
[0]: https://gist.github.com/ageis/a91f36ca99c252291a00 [1]: https://github.com/freedomofpress/grsec/ [2]: https://micahflee.com/2016/01/debian-grsecurity/ [3]: http://lwn.net/Articles/668876/
https://copperhead.co/android/
Which of course ,raises the question: Why doesn't Google integrate this into android, or at the very least for a secure/business version of android ?
Arch don't even have coreutils "by default". Yes, I know, you're supposed to install them anyway, but if you follow the standard install guide, there is no GRsec.
This does not seem to be a responsible disclosure of the vulnerability (keep in mind it was posted on their blog 5 days ago).
^-- this version should do that automatically
grep commit_creds /proc/kallsyms
grep prepare_kernel_cred /proc/kallsyms
Then update addresses as shown in one of the code snippets: _commit_creds commit_creds = 0xffffffff81094250;
_prepare_kernel_cred prepare_kernel_cred = 0xffffffff81094550;As a normal user, grepping these values I actually get 0000000000000000. I can't imagine these being the actual values. Is it possible that because I remount my /proc with the hidepid=2 option the values are not visible for normal non-root accounts?
EDIT: The obvious question I should have asked is which distro you are running. Also, as others have pointed out, hoping that the attacker can't read kallsyms from the machine he's attacking is not really a good defense plan.
Exploiting from root to root doesn't make a lot of sense. If the values are not retrievable as normal user this exploit can't be used.. Right?
Think of it like the manual of a nuclear missile launcher. Obviously they don't want to give that out to everyone. But if you can break into the room with the launcher's control panel, you've still caused a major security breach even if you have no idea what to do next. Having the manual just makes your job easier, but the attack was that you broke in in the first place; they can't count on you being unable to figure out how to work the panel.
Also, if you're running a binary kernel (for instance, a kernel built by your Linux distro), the addresses in kallsyms are going to be constant for everyone running that distro. Hiding kallsyms for non-root users is primarily useful for people who build custom kernels.
Production-level malware often also has code that doesn't depend on having access to kallsyms and is more advanced (e.g., starting from the system call interrupt vector and disassembling it and seeing what addresses are jumped to). Using kallsyms is good for keeping a simple proof-of-concept exploit readable.
Suppose you have a vulnerable CentOS 7 system that you want to exploit - you could get the proper addresses from your own CentOS 7 VM running the same kernel, apply those to a modified exploit compilation, and run that compilation on your target host.
Also, it is not bullet proof because apparently there are lots of info leaks in linux and I think linux also does not reboot after a panic (http://www.cyberciti.biz/tips/reboot-linux-box-after-a-kerne...) so if the entropy for KASLR is small enough you can retry very aggressively. Though in this particular instance if you have to wait 30 minutes between each try that would kill brute forcing.
/proc/sys/kernel/kptr_restrict
For me, this gave me 0, but if you cat this it should give you 1. So essentially it's a setting but I'd wager it's not related to you remounting /proc.Just for curiosity's sake, from searching around it seems that this particular security feature (hide kernel pointers for unprivileged users) seems to have originated from this commit (which in itself implements a broader and more general security feature): http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.g... - but it's often not enabled.
So it's not ASLR or anything to do with filesystem options (per se), but rather a custom "kptr_restrict" kernel vs. userspace security feature provided by the kernel:
"[...] The %pK format specifier is designed to hide exposed kernel pointers, specifically via /proc interfaces. Exposing these pointers provides an easy target for kernel write vulnerabilities, since they reveal the locations of writable structures containing easily triggerable function pointers." (Dan Rosenberg, 2011-01-13 - nice.) (Of course if there's no ASLR and one knows which distro is being targeted, it's possible to find those values on another machine and to just bake them into the exploit, as others have pointed out. Also, other channels exist for finding these addresses, etc.)
$ uname -r
4.3.3-2-ARCH
No root: $ ./cve_2016_0728 PP_KEY
uid=1000, euid=1000
Increfing...
finished increfing
forking...
finished forking
caling revoke...
uid=1000, euid=1000
Only took about 25 minutes on a Lenovo core i7. That's kind of scary.EDIT: Actually it seems that atomic_t is 64 bits long with x86_64 these days, so no hope of overflowing.
include/asm-generic/atomic-long.h:
#if BITS_PER_LONG == 64
typedef atomic64_t atomic_long_t;
...
#else
typedef atomic_t atomic_long_t;
Just checking it with a 32-bit VM with the latest upstream kernel.EDIT: No, I was wrong. atomic_t is 32 bits also with 64 bit architecture. Must be something else then, let's see.
This issue affects the Linux kernels as shipped with Red Hat Enterprise Linux 7 and will be addressed in a future update.
https://bugzilla.redhat.com/show_bug.cgi?id=1297475
Premature blog post?
[ohadmin@localhost shm]$ ./cve_2016_0728 PP_KEY
uid=99990, euid=99990
Increfing...
This is taking a long time. I disabled SELinux and it has been cranking away for a while now. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1140 ohadmin 20 0 8428 388 296 R 100.0 0.0 9:25.17 cve_2016_0728
No need to test on CentOS 6. Forgot how ancient that kernel is.Update: I am not having any luck getting this to work on CentOS 7. I even completely disabled SELinux (selinux=0 vs setenforce 0) Anyone else getting this to work?
It appears smaps may be preventing the exploit from working.
Is there any other other of Linux/Mac/Windows/Android dist that have some type of security framework capture this kind of issue?
Well, Android and most RHEL-derivated distros use SELinux and it can mitigate this kind of problems (assuming it is well configured) and Ubuntu has "AppArmor" but I don't know if it mitigates this issue as well.
This is not a jab at open source software, just at the general statement which people like to throw around when referring to the security of open source software; "It's open so it must be safe!"
Suppose we have two projects with 100% identical source code, which are mathematically proven to both contain 0 bugs, and which have been extensively audited by third parties.
Despite being identical, the open source version will be much more secure for end users, because the source code and machine code can be obtained, compiled and distributed by a much larger number of competing parties.
This allows users to compare compiler output and run-time behavior, to verify that software being run is actually the software being written, and to ensure that the software is not surreptitiously modified by the publisher during its distribution.
With closed source software, even if developers write a 100% perfect codebase, the end users have no way of knowing whether they are actually getting that specific code base in their binaries, as there are legal and technical barriers in place preventing them from reliably making that verification for every change.
Black hats (trust me, I've known a few) will gladly attack proprietary software (usually with more glee, because there's far less review of proprietary software in general). Using proprietary software doesn't save you from black hats. But it does give you more chances of white hats finding the bugs sooner.
Security isn't a binary state, it's a lifestyle. All code has bugs, and almost all bugs can be security bugs. Taking steps to add more layers to your security is what you should be doing, not arguing that "because the software is free someone found it!".
uid=10000, euid=10000
Increfing...
finished increfing
forking...
finished forking
caling revoke...
uid=10000, euid=10000
sh-4.2$IIUC SMEP is on Sandy Bridge processors too.
EDIT:
[chris@f23m cve20160728]$ ./cve_2016_0728 PP_KEY
uid=1000, euid=1000
Increfing...
finished increfing
forking...
finished forking
caling revoke...
uid=1000, euid=1000
sh-4.3$ #define COMMIT_CREDS_ADDR (0xffffffff81094250)
#define PREPARE_KERNEL_CREDS_ADDR (0xffffffff81094550)