DISQUS

DISQUS Hello! Matasano Chargen is using DISQUS, a powerful comment system, to manage its comments. Learn more.

Community Page

Jump to original thread »
Author

What We’ve Since Learned About Leopard Security Features

Started by tqbf · 10 months ago

There are over 100 comments accumulated on my last Leopard post. As
usual, they’re better than the post itself. Since you’re probably in a
hurry, I’ll spare you the effort of poring over them, and instead
present our findings to date.

OS X Runtime ... Continue reading »

24 comments

  • It is strange how people keep saying that Robert Watson first disclosed the systrace problem. Quoting you:

    "Systrace has a well-known vulnerability, first documented by Robert Watson and published formally this year at Usenix WOOT."

    First documented? Let me quote the systace(1) manual page itself:

    BUGS
    Applications that use clone()-like system calls to share the complete address space between processes may be able to replace system call arguments after they have been evaluated by systrace and escape policy enforcement.

    It says the same thing as Robert Watson's paper. That comment was added to the manual page on July 21, 2002, by Niels Provos, the original author.

    It is a hard problem, which is why it has not been fixed. But come on, the problem was documented since nearly day 1.
    We'd welcome fixes for it, but try to keep the diff under 12,000 lines, ok? That's how hard the problem is..
  • Thomas, a quick correction: The code signatures are not enforced by the TMSafetyNet kext. This kext is a kext for Time Machine. Code signatures are verified by the xnu kernel (not by a kext, but by the actual /mach_kernel that you boot, the core).
    Check cs_invalid_page() in bsd/kern/kern_proc.c (xnu-1228), cs_validate_page() in bsd/kern/ubc_subr.c and load_code_signature() in bsd/kern/mach_loader.c. Well, the kernel actually only calculates SHA-1 message digests on the (code) pages and compares them to known ones, I do not know yet which userspace program does the certificate validation.

    Also, reading your comment "you’d be a little shocked to find one in privileged OS X code." I wasn't quite sure whether I missed the irony again. But no, I'm not shocked, not at all. Come to think of it, I totally expected today's Secunia advisory on CUPS (it was a 1-byte stack overwrite, a little bit harder to exploit but potentially possible on OSX as well). Actually, I expect more of the same for CUPS... It's certainly one piece of software on the top of my to-sandbox list.
  • I actually think stack protection is still relevent. Particularly, the client-side attack surface of large applications like Safari, iChat and Mail. Let alone the fact that there are enough third party developers that are not security conscious and developing for Mac OS X.

    I also generally like improvements where compilers and operating systems protect me from potentially unsafe code.
  • I agree with Theo.
  • Dave: Actually, I think Apple screwed up big time with stack protection in Leopard. My testing so far is preliminary, so please take the following with one or possibly more grain(s) of salt.

    I've looked at XCode today. Long. I haven't been able to find a single option to enable stack protection, neither for a project, nor globally. Nothing in the help either. What's Apple's famed dev environment, the Visual Studio for OSX? XCode, I thought.

    Also, compiling my own C code with -fstack-protector (using the system gcc) yields binaries that have undefined references to __stack_chk_fail and __stack_chk_guard. I don't see these undef refs neither on Safari, iChat, Mail nor on CUPS.

    @Thomas: mDNSResponder doesn't have these either, which makes me doubt your earlier statement. What did you see that made you claim that it was in the first Leopard post?

    Actually, I have concers that even with stack protection enabled, due to the way dyld works, things may be working suboptimal. But that needs further research still.
  • On it's own stack protection is barely useful.

    But it is still very relevant when used with other things:

    1) Best-effort ALSR, especially top-of-stack and (as you
    mention) the shlib linker.
    2) W^X on the _entire_ address space (the mprotect
    component of this is often overstated though as it
    only gets involved in the 2nd or 3rd step of an
    attack, and the combination of all these things
    makes lib-return very hard.
    3) A sprinking of resistance in libc such as
    malloc/free paranoia, dtor/atexit carefulness, etc.
    4) PIE, just because it affects the known values on your
    stack SO MUCH..

    If you mix all 4 of these things together with compiler assisted stack protect, it is a very difficult (hostile)
    programming environment for an attacker.

    Those are the most effective schemes. Other crazy schemes have gone through our heads in the years, such as malloc padding things to unmapped pages exactly, or non-readable code segments (on platforms that support it, but you need to fix the switch-table code in compilers...) but most fancy things start causing problems. The amount of non-security third party bugs you start helping people fix gets unmanagable...
  • ... though do note, Theo, that Watson "documented" this in a mailing list post like 7 years ago.
  • Ralf: I am guessing that you are right and I'm wrong. I think I may have been misinterpreting the offset call at the beginning of subroutines (a PIE artifact).
  • OK, you beat me. 7 years, by the way, is older than systrace(1) itself.... it being only 5 years ago.

    Unless you mean the generic TOCTOU problem. Well, that was known about way more than 7 years ago and documented in piles of other academic papers. It might be interesting to see how far back that goes.

    It is access(2) or stat(2) all over again.
  • OK, you beat me. 7 years, by the way, is older than systrace(1) itself.... it being only 5 years ago.

    Unless you mean the generic TOCTOU problem. Well, that was known about way more than 7 years ago and documented in piles of other academic papers. It might be interesting to see how far back that goes.

    It is access(2) or stat(2) all over again.
  • I agree that the underlying class of vulnerabilities is ancient. I'm not standing by the number "7", just noting that when we vetted the paper for WOOT, it was noted that there was an old mailing list post behind it --- making it a bit weird as a new piece of research.
  • Hrm the SSP/ProPolice is confirmed? From what I saw they shipped with GCC 4.0.1, and SSP went into mainline in GCC 4.1?

    I'm guessing from what someone else commented here they attempted to put the protection in themselves, and screwed it up?
  • jf: yes, SSP support in the OSX 10.5 system gcc is confirmed. Have a look at the gcc-5465 source to see for yourself, especially gcc/ChangeLog.apple. It is not present on 10.4.x gcc (for which the src is available as well) nor is it present in the stock gcc 4.0.1.

    It does not look like Apple compiled anything with -fstack-protector. Reasons are unknown. For an actual implementation of the stack protector you have to look into libgcc-8.1 (which, funnily enough, is derived from gcc-4.2.0).
  • The heap is NX when you compile 64-bit.

    Try compiling your test program with
    gcc -arch x86_64 test.c

    This would require a 64-bit processor like the Core 2 Duo or whatever comes with the Mac Pro.


    Also, the main executable(but not dyld) is randomized if you compile with -Wl,-pie.
  • "I could now waste your time with a discussion of how valuable stack and heap randomization is, but it’s a moot point: the OS X stack and heap don’t appear to be randomized."

    I'd be interested in a discussion of that value (or lack thereof).
  • Start with these points:

    - All sorts of subtle little bugs that people don't really audit for will disclose either (a) actual offsets into the heap or (b) the secrets used to generate those offsets.

    - Inputs to programs can drastically influence the predictability of allocations even when they are randomized.

    - In a significant number of cases, you can get leverage control of a CPU register and any known large span of opcodes to land code where you need to.

    - When you start randomizing the heap, you wind up in a losing battle against performance (the biggest problem in allocator design is fragmentation).

    - Retries.

    I know the conventional wisdom is that, done right, ASLR is very effective. And I do less shellcoding than almost anyone else involved in this argument. But I'm not sold on ASLR, and I am sold on things like Sandboxes and Systrace.
  • I am glad that Systrace is providing opportunity for such stimulating discussions. As Theo stated, the problems that Robert described in his WOOT paper were all well known. Robert's contribution was a concise summary of the various problems.

    However, the TOCTOU issues in Systrace and their solution were even mentioned in the Systrace paper. The original implementation used a local-aside buffer for copyin. As a result, the system call arguments were stored in kernel address space and could not be changed by any sandboxed process.

    Other issues like flipping symlinks were resolved in a similar way. Once Systrace has canonicalized the path, the kernel is told that the path may not contain symlinks.

    If people are really interested in this topic, I recommend reading Tal Garfinkel's paper on the Ostia system (2003) which presents a similar list of problems as those presented by Robert.

    Thomas, I am still waiting on your "Virtual Honeypots" book review :-)
  • Niels: it's coming! The good news is, like 4 different Matasano people have now had a hand in it. =)
  • A copyin buffer for the system call arguments is not nearly enough to solve this problem. It requires nearly an entire rewrite of how the kernel handles system calls.

    ioctl(), fcntl(), bind(), connect() and and a host of other system calls have arguments which point to a buffer which contains the important stuff -- those buffers are still very much attackable.

    ioctl() actually is probably the hardest. In most BSD-derivatives the size is encoded in the 2nd argument, but the interpretation of the 3rd argument is not done until you hit deep driver code.

    A simple approach might be to "lock" the userland address space in such situations to provide atomicity, but that is very SMP hostile if not done perfectly.

    If the problem was simple it would have been solved a long time ago.
  • It doesn't seem like the answer is "canonicalizing" the ioctl payload between userland and time-of-use. It seems to me like you can solve 95% of this problem by not letting untrusted code open sensitive devices or issue sensitive ioctl calls.

    There is certainly some trivial case of an ioctl that every program needs to issue that has an ambiguous interpretation. I am missing it. What is it?

    Great stuff, though. Thanks!
  • > First documented? Let me quote the systace(1) manual page itself:
    >
    > BUGS
    > Applications that use clone()-like system calls to share the complete address
    > space between processes may be able to replace system call arguments after
    > they have been evaluated by systrace and escape policy enforcement.
    >
    > It says the same thing as Robert Watson’s paper. That comment was added to
    > the manual page on July 21, 2002, by Niels Provos, the original author.

    Just to clarify history here slightly: the man page comment was added by Niels shortly after my private e-mail to him on July 19th, 2002 raising these issues and expressing my concern over the potential vulnerability of Systrace policies to such attacks.

    The point of the recent paper was to more thoroughly explore this class of vulnerabilities and previously undocumented exploit techniques (this being a workshop on exploiting vulnerabilities), not just in Systrace but in the general class of software wrappers used to enforce security policies. It turns out many anti-virus engines suffer from exactly the same class of problem, and many end users depend heavily on the reliability of anti-virus engines. It is very important that weaknesses in the approach, and especially the ease of exploiting the vulnerability, be understood by the more general software authoring community. Unlike OpenBSD users, these end-users will be significantly less sophisticated when it comes to avoiding downloading and running binaries from unreliable sources, and they don't have a firm OS foundation to protect them, hence running with anti-virus software in the first place.

    Robert Watson
  • The Parental Controls feature, or at least the portion of it that allows an admin user to create a Safe account under which only specific apps can be executed, has been in place since, i believe, Panther, but just never really touted.

    I'd briefly mentioned it here:

    http://theappleblog.com/2005/02/15/best-from-ap...
  • I'm just curious on the firewall comment...what OS comes with a outbound firewall enabled by default? It seems more like something which was on your wishlist and which you only are mentioning because you're disappointed...It seems like there are plenty of other things you could put on that same wishlist and call out in this article :S
  • concerning the filtering of outgoing connections: there is a open source project at sourceforge.net that aims at that problem (http://sourceforge.net/projects/ppfilter).

Add New Comment

Returning? Login