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 are authorized before userland application is connected. 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 code available at Github, https://github.com/gdbinit/can_I_suid.