Can I SUID: a TrustedBSD policy module to control suid binaries execution

Let me present you another TrustedBSD policy module, this time to control execution of suid enabled binaries.
The idea to create this started with nemo’s exploitation of bash’s shellshock bug and VMWare  Fusion. It was an easy local privilege escalation because there are many Fusion suid enabled binaries. This got me thinking that I want to know when this kind of binaries are executed and if possible control access to them. For the first part you don’t really need this module because the audit features available in OS X can give you this information. I’m more interested in having decision power over what is executed. Or it’s just another nice example of how TrustedBSD is so interesting and powerful and why it’s annoying that Apple is closing KPI access to it (latest SDK warnings say it was never meant to be a KPI).

There are two parts to this. The first is the kernel driver that detects execution, controls access, and notifies userland. The second is a small userland application that receives the kernel notifications, asks the user for a decision, and sends back the answer to the kernel.
The execution is blocked until a decision is made or a timeout is reached (default is 5 seconds, you probably want to increase this value).

To avoid any deadlocks all binaries before userland application is connected are authorized. When the userland finally connects it receives a list (displayed as user notifications) of all the suid binaries that executed during the boot process (from my tests this is zero in Mavericks).

Because of the changing nature of TrustedBSD started in Mavericks, this code only works with Mavericks as it is. If you want to make it work in Mountain Lion or Yosemite, you need to change the hook prototype and compile it with the correspondent SDK.

The userland application needs some work due to my crap Cocoa skills :-). The kernel extension has a few points that need a decision (what to do in error cases mostly), authentication of the userland process (it’s not hard to do), and probably more process information.

A friendly tip: The kernel control interface is used for userland/kernel communication. Because the volume of data exchanged is very low it’s ok for this. If you are thinking about using this  interface for high volumes forget about it. It has some weird bug where it starts losing data and not able to keep throughtput (error 55 is what you start to experience).

Source available at Github, https://github.com/gdbinit/can_I_suid.

Have fun,
fG!

12 thoughts on “Can I SUID: a TrustedBSD policy module to control suid binaries execution

  1. “authentication of the userland process (it’s not hard to do)”

    Really? How would you do this?

    Accessing the code signature of the userland process is not part of any KPI (though nor is TrustedBSD, so I guess that’s less of a concern), embedding some sort of key isn’t really secure and embedding a hash of the userland process makes updating the userland process impossible without updating the kext.

    Maybe I’m not being creative enough.

    1. Start by controlling the path to the process.
      Because the kernel doesn’t have codesigning KPI doesn’t mean the kext can’t implement a integrity/signing mechanism.
      Hell, you can even have the kext to modify itself and store the hash of the binary, as long you trust the binary you update in userland and take the risk of a race condition while updating it.

      It is indeed a fight between usability and security.

      1. To really do that you have to use something like Intel TXT, otherwise you would always have the chicken and the egg problem since the machine can be compromised (and then you cannot trust userland or even kernel land in the first place).

        1. Well, nothing new there. Intel TXT itself will have vulns and it’s not a magic bullet.
          The problem will never end, it’s a question of adding more layers.
          The moment you are target of more sophisticated attacks it means you have more to worry about than computers ;-).

  2. “Start by controlling the path to the process.”

    How? There is no KPI (that I could find) to find out the full path of the process connecting to the kext.

    “Because the kernel doesn’t have codesigning KPI doesn’t mean the kext can’t implement a integrity/signing mechanism.”

    True, but it’s the details of that implementation that interest me.

    “Hell, you can even have the kext to modify itself and store the hash of the binary, as long you trust the binary you update in userland and take the risk of a race condition while updating it.”

    How does the kext modify itself without invalidating its own code signature (as doing so would prevent it from being loaded automatically on next boot)?

    1. There’s no KPI before Yosemite so you need to hack your way around (hint: you just need a structure offset). You can’t do all the good stuff with KPIs 😉
      For codesigning you just need to import a crypto library into the kext and use a pubkey to verify it (Yosemite seems to have progressed in this chapter). It’s just a bit of work to port and fix the library but not mission impossible.
      Code signing is about code and not about the writable data sections/segments. Those can be used for this purpose.

  3. .. or .. you could just use kauth 🙂 vnode_authorize gets called on exec. vap->va_mode & (VSUID | VSGID) then shows if it’s a SUID. No need for MacF.

    1. Sure but:
      – TrustedBSD is called before vnode_authorize.
      – TrustedBSD is less hot than vnode_authorize.
      – TrustedBSD is more flexible than kauth.
      – And I don’t want TrustedBSD to be closed ;-).

      Kauth is useful for some stuff that TrustedBSD is unable to reach.

      1. To which one would argue that:

        – TrustedBSD is called before vnode_authorize:
        yeah, but both get called before you actually kexec. And Kauth will remain open – MACF won’t.

        – TrustedBSD is less hot than vnode_authorize.
        hot = ?

        – TrustedBSD is more flexible than kauth.
        Absolutely. If you can call mammoth structures of mpo callouts “flexible”. More granular, definitely. But also subject to change. 10.10 adds .mpo_system_check_sysctlbyname, . mpo_check_vnode_check_rename , which weren’t there before. So the policy needs to be recompiled every major xnu release – by comparison, kauth hasn’t changed much since inception.

        – And I don’t want TrustedBSD to be closed ;-).

        Neither do I, but there’s what WE want, and there’s what Apple does: Apple uses it for sandbox.kext and that wretched AMFI (which has no made its debut in OS X, no doubt to implement the trust cache and to secure kext loading in general).

        1. It does look indeed that MACF will be closed. Even in that case it’s still a lot more powerful than kauth.
          vnode_authorize is called more often than TrustedBSD hooks (Technical Note TN2127).
          If you are looking at the small picture which is suid control only than kauth is more than fine for the task. For the bigger picture it’s not enough. But it’s a matter of personal taste, I use both for different tasks.
          Kext loading is as wide open as it was before, but that’s to be proven later this year or next year ;-).

  4. – Or it’s just another nice example of how TrustedBSD is so interesting and powerful and why it’s annoying that Apple is closing KPI access to it (latest SDK warnings say it was never meant to be a KPI).

    I’ve just compiled the source code on El Capitan and although I see the #warning “MAC policy is not KPI, see technical Q&A QA1574”, the sample still compiles and I’ve successfully loaded the kext into the kernel and it’s working all right. Some time ago it was said that this will be removed in the next major OS X release, but that has happened with Yosemite as well as El Capitan, but this is still available. Do you have any information about why this is the case and if we’re allowed to use it or not; when it will be removed completely?

    1. That API is not stable anymore. Hooks are different between versions, new hooks are added, and so on.

      So it’s “use at your own risk” these days.

Leave a Reply

Your email address will not be published. Required fields are marked *