How to fix rootpipe in Mavericks and call Apple’s bullshit bluff about rootpipe fixes

The rootpipe vulnerability was finally fully disclosed last week after a couple of months of expectation since the first announcement. It was disclosed as a hidden backdoor but it’s really more something related to access control and crap design than a backdoor. Although keep in mind that good backdoors should be hard to distinguish from simple errors. In this case there are a lot of services using this feature so it’s hardly a hidden backdoor that just sits there waiting for some evil purpose. Apple doesn’t have a stellar security record so the simple explanation has a good chance to prevail over the backdoor story.

Anyway that’s not what really matter for this post. The most important issue is that a fix was made available only for Yosemite 10.10.3. Every other OS X version is left vulnerable. While this is a local privilege escalation vulnerability there are many scenarios where it can be used (you don’t audit every single installer and software that runs on your Mac, do you?). It is extremely reliable and can be used in different ways other than just creating a suid binary.
The vulnerability author wrote the following regarding this issue:
“Apple indicated that this issue required a substantial amount of changes on their side, and that they will not back port the fix to 10.9.x and older.”

So essentially Apple refuses to patch this in all versions except the latest one because it’s apparently too much work. There is no official statement from Apple regarding the EOL (End of Life) status about all previous OS X versions so this course of action is quite strange. Even stranger when Apple backports some security patches to those older versions so they are implicitly not yet dead versions.

In this situation what can we do?
We can try to verify what is the real impact of Apple’s fix and call their bluff if we can prove that we are able to produce a fix without significant changes to the operating system. Challenge accepted!
Continue reading

How to bypass Google’s Santa LOCKDOWN mode

Santa is a binary whitelisting/blacklisting system made by Google’s Macintosh Operations Team. While I refer to it as Google’s Santa it is not an official Google product. It is based on a kernel extension and userland components to control the execution of binaries in OS X systems.
It features two interesting modes of execution, monitor and lockdown. The monitor mode is a blacklisting system, where all binaries except those blacklisted can run. The lockdown mode is a whitelisting system, where only the whitelisted binaries can run and everything else will be blocked. This is the mode we want to attack and bypass since it’s the most interesting one from an attacker’s perspective.

The system works by having the kernel extension to notify the userland daemon about every new process that is executed in the system. The kernel extension retrieves this information using the Kernel Authorization (kauth) feature available since OS X 10.4. Essentially a callback is installed and the Santa driver will be notified every time a process is executed. This means that exec() and variants will result in a notification to the driver that will then decide to send the event to userland or not.

The userland component has an associated database that can whitelist or blacklist binaries based on path, certificate, and hashes (I think I’m not wrong on this). The code signature feature is interesting because it allows you to whitelist or blacklist an entire publisher. For example a company could easily restrict all the software that is allowed to run in their systems based on their code signing certificate. By default the lockdown mode install will whitelist Apple’s and Google’s certificates, else the system would enter a deadlock. Assuming we are not tampering with Santa’s binaries and attacking its implementation (if we can run kernel exploit code we can easily disable it) can we bypass the lockdown mode if we want to run our code that is not allowed to run?

Yes we can, and it’s very easy to do it :-)

What Santa essentially controls and restricts is exec and variants. But that’s not the only possible way to run arbitrary code. There is the obvious way of exploiting something and running our shellcode/ROP payload, and there are also dynamic libraries. Because Santa only controls exec we can run whatever code we want via a dynamic library injected using DYLD_INSERT_LIBRARIES without tampering with any Santa binary. We can go further and instead of putting all our code inside a dynamic library we can use it to run regular binaries that are not authorized to in lockdown mode.

We simply need to piggyback on any Apple signed binary (remember the system deadlock problem) with DYLD_INSERT_LIBRARIES to inject our library. For example any command line utility such as /bin/ls will do the job.
How can we execute other binaries using an injected dynamic library? That’s quite easy using some obscure and deprecated dyld functions. For example NSCreateObjectFileImageFromMemory and NSLinkModule would allow us to load an arbitrary executable into memory and execute it (please refer to Mac Hackers Handbook Chapter 9 and MemoryBasedBundle example by Apple).

The workflow is very simple. We inject our library into a whitelisted binary, load the unauthorized binary with those two dyld functions, and start it by calling its entrypoint (main) function. Because this doesn’t trigger a second exec we just bypass Santa controls. The original process will continue execution in the unauthorized binary and that’s it.

The sample code uses the deprecated APIs, which can be removed anytime (although they have been marked deprecated for quite a few OS X major versions). There’s really no need to use those APIs because we can do all their work ourselves. Most of the work is related to linking, so we could implement ourselves a simplified linker or re implement those functions and have dyld do all the dirty work for ourselves. As long we are able to inject a dynamic library we are able to bypass Santa. The DLL hijacking issue recently presented by Patrick Wardle could be used to plant the library and then execute any APT material.

The easiest way to fix this is to remove the possibility of library injection via DYLD_INSERT_LIBRARIES. The next post contains a kernel extension that implements this by injecting a __RESTRICT segment into certain binaries we want to restrict injection. The real problem is that DYLD_INSERT_LIBRARIES feature should not exist by default and should be instead a system setting disabled by default. Stefan’s SyScan presentation is a good read regarding the problems of default features and unfixed stuff in iOS (and OS X).

Proof of concept code:
Hello Santa Bye Santa – https://github.com/gdbinit/hello_santa_bye_santa

Last time I tested this was a month ago or something. Judging by the commits logs I guess the issue isn’t fixed so it should still work. This is technically a zero day ;-). I wanted to present it a SyScan’s WhiskeyCon but then decided not to, and now I’m disclosing it because the next post about rootpipe fix requires its disclosure :-(.

Enjoy,
fG!

P.S.: Defense is hard, in particular when working on a minefield such as OS X ;-)

Update: This is a very nice blog post talking about white-list systems expectations. This is exactly what’s missing from most security products. Right after their features they should discuss their assumptions, shortcomings, and expected scenarios. You know, most of the times the expectations between who builds the product and who uses it are quite far away. Yes, it’s probably more wishful thinking than anything else. Commercial products will never do this, they are too afraid of losing customers ;-).

BadXNU, a rotten apple! – CodeBlue 2014, SyScan 2015 slides and source code

The last SyScan is almost here so it’s time to get again into a plane and travel to Singapore.
This means that the slides and source code can finally be released. Below you can find the archive with both presentations slides (they are slightly different, SyScan fixes/upgrades a few things) and full source code for both rootkit/kext loaders.

I hope you enjoy them; they are quite fun techniques, in particular the second one which now I sort of regret to disclose because it’s so cool.
I’ve also written a book chapter about both techniques (53 pages before editing) which add a few more tricks. I’m working on the book so hopefully it will finally come out this year.

The archive password will be released on the day of my presentation (27th March) so keep an eye on Twitter and SyScan website. If you crack it before that keep its contents private ;-).

If you are at SyScan feel free to have a chat. I’m there to meet new people and also learn.

Hope you enjoy,
fG!

Archive:
https://reverse.put.as/wp-content/uploads/2015/03/syscan_pack.rar
Dropbox Mirror:
https://www.dropbox.com/s/68j5nja80cxxova/syscan_pack.rar?dl=0

Update: The archive password is “syscan_rules_blackhat_sucks!”.
The final version presented at SyScan (really minor changes) can be download here.
The full source code is available at GitHub, diagnostic_service and diagnostic_service2.

https is now (finally) supported!

Hummm this is something that I should have done a long time ago but was always too lazy since there’s not highly critical information here (except some hashes and my PGP key/id).

Anyway, you can finally access the blog over https://reverse.put.as.
I still need to understand if there’s any impact on Google search stuff by moving it to https only.

Better late then never. Oh and fuck you David Cameron and your stupid populist ideas ;-).

Have fun,
fG!

Happy New Year!

A few days late but, Happy New Year!
2014 is gone and it was an interesting year. Learnt quite a few new things in different areas, created tons of code, and got a couple of very interesting ideas to explore in 2015.

It also ended in a great way with a visit to CodeBlue to present BadXNU, a rotten apple.
If there’s city and country I always wanted to visit, those were Tokyo and Japan. My (unusual) quite high expectations were matched by a very interesting mega city. I was quite surprised with its efficiency for such a gigantic town. And because I don’t speak Japanese I loved every “lost in translation” moment, where shop attendants kept speaking in Japanase. I don’t know, I just love small things :-). Definitely can’t wait to get back to Tokyo and keep discovering the city; there are too many things to see, and still missing the rest of Japan. Phewwww!

CodeBlue definitely shattered my expectations. It was impecably organized (many thanks to Kana, Kentaro, Tessy, and everyone else for their amazing work and effort), was packed on both days (!), had a curious and motivated audience (at least that was my feeling), and a great program. Definitely highly recommended if you want to attend or speak there.

Unfortunately you will have to wait for SyScan 2015 for the slides and source code. I always like to release everything as soon as possible but this time it’s special so please allow me the exception. I guess it will be worth the wait ;-).

2015 is starting with extremely motivated work on the OS X Rootkits book. Due to many reasons the project was stopped but I finally got the time and focus to resume work and make it a reality, together with my co-authors nemo and snare. I really hope it will be worth the wait, we are going to do our best. So keep an eye for it.

Last but not least, I’m linking to the SyScan 360 slides. I forgot to write a post about SyScan360 and link those slides. The slide count is a bit bigger than the ShakaCon set (I can’t remember the differences now but I probably tuned some details and added a few things).

SyScan 360 – Fuck You Hacking Team

Hope you have a great year and stay healthy.
Have fun,
fG!

Patching what Apple doesn’t want to or how to make your “old” OS X versions a bit safer

Today a local privilege escalation vulnerability was disclosed in this blog post. It describes a vulnerability in IOBluetoothFamily kernel extension (IOKit is a never-ending hole of security vulnerabilities…).

Mavericks and most probably all previous versions are vulnerable but not Yosemite.
The reason for this is that Apple silently patched the bug in Yosemite.
This is not a new practice, where Apple patches bugs in the latest and newly released OS X version and doesn’t care about older versions. Mavericks 10.9.5 update was released more or less around Yosemite date and this doesn’t look like a last minute bug found (although I’m going to confirm this). I bet that the bugs disclosed at SyScan 2013 by Stefan Esser still aren’t patched in Mountain Lion.

The blog post authors seem to experience the same “we don’t care attitude”. Their conclusions state:
“We contacted Apple on October 20th, 2014, asking for their intention to back-port the security fix to OS X Mavericks. Unfortunately, we got no reply, so we decided to publicly disclose the details of this vulnerability: Yosemite has now been released since a while and is available for free for Apple customers; thus, we don’t think the public disclosure of this bug could endanger end-users.”

The patch is very simple with only two instructions. With some luck we can patch it ourselves. What we need is a bit of unused space for installing the patch instructions. The mach-o header is usually a good place in userland but in kernel extensions you get a no execute (NX) kernel panic. They are also not wired memory so it’s not a good place to install a patch. We are left with alignment space.
If you search there are quite a few places with 15 alignment bytes (tip: load the driver into IDA, do a text search for align or a byte search for 90 90 90). That’s good enough for our patching, and we will need two of those islands since my proposed patch is 19 bytes long.

The two patch instructions are:
test ecx,ecx
js location

To install the patch we need to replace the first original instruction with a jump to the first island. Then we restore the original instruction and add the new patch instructions. We need to use a second island because the first doesn’t have enough space for this.
The new code should be something like this:
original_address:
jmp first_island
nop
remaining original_instructions
(…)
first_island:
jge location (original instruction)
test ecx,ecx (patch instruction)
jmp second_island
second_island:
js location (patch instruction)
jmp next_original_instruction

For Mavericks 10.9.5 you want to patch the following file /System/Library/Extensions/IOBluetoothFamily.kext/Contents/MacOS/IOBluetoothFamily.

Use the following file offsets and bytes:
Original instructions:
0x2855C: E9 B0 F7 FF FF 90
First island:
0x27D11: 0F 8D 43 0B 00 00
0x27D17: 85 C9
0x27D19: E9 23 2E 00 00
Second island:
0x2AB41: 0F 88 13 DD FF FF
0x2AB47: E9 16 DA FF FF

Save file, copy back to the original location, touch /System/Library/Extensions and reboot :-). Most probably this patch can be improved and reduced in size using smaller jump offsets if nearer islands are available. I didn’t bother to check.

Now go write to Apple and ask them to issue a proper patch. This total crap security policy must come to an end. Just in case you are wondering if this is an isolated case, check this Google Zero blog post. Two bugs that remain unpatched on OS X ;-).

Oh, this will break the code signature but in Mavericks that’s just a warning and not a fatal error. You can resign with a developer kext certificate if you have one.

Have fun,
fG!

P.S.: Another fine example of this crap security policy is that Apple fixed a few integer overflows in C++ code of libkern in Yosemite but didn’t bother to backport to Mavericks 10.9.5.  This is just insane…