Apple recently released Mac OS X 10.5.4 with accompanying security updates for 25 vulnerabilities. Notably absent, however, is a fix for the recently brouhaha’d ARDAgent.app local privilege escalation vulnerability. The exploit is extremely simple and unfortunately, it seems that the fix is not; otherwise Apple would have fixed it in this batch. For more information on the exploit including temporary fixes and workarounds to protect yourself until Apple fixes this vulnerability, see the full write-up at MacShadows.com.
In the interest of fully understanding Mac OS X security issues, let’s dive in and see how this vulnerability works. As a reminder, the vulnerability is that ARDAgent.app, a set-user-id root executable, responds to the “do shell script” Apple Event, effectively running arbitrary commands as root.
Applications must announce that they can receive Apple Events before they may be scripted. In Cocoa applications, this is done by setting the NSAppleScriptEnabled property to “YES” in the application bundle’s Info.plist file. In Carbon applications, an application is made scriptable by simply calling the AEInstallEventHandler() function. AEInstallEventHandler() lets the application define which Apple Events it can handle and supply the handler functions for them.
ARDAgent.app did not do anything special in order to respond to the “do shell script” Apple Event, this event is defined in the StandardAdditions Scripting Addition in /System/Library/ScriptingAdditions. Scripting Additions are dynamic libraries (dylibs) that will be loaded automatically by the Apple Event handler if the application receives an Apple Event that is defined in them. There are several Scripting Additions in /System/Library/ScriptingAdditions, but they may also potentially be found in /Library/Scripting/Additions or ~/Library/ScriptingAdditions.
Interestingly, ARDAgent.app calls AESetInteractionAllowed() with kAEInteractWithSelf after installing its own Apple Event handlers which is supposed to restrict the processing of Apple Events to only those sent by the process itself. It obviously does not seem to have its intended effect in this case.
This is a pretty isolated vulnerability not a massive security hole in AppleScript. Set-user-id executables should not be scriptable and ARDAgent.app appears to be the only application that violates this.
UPDATE @ 20080704: As mentioned in the MacShadows security forums from the link in the comments below, SecurityAgent is also susceptible to this, but only when SecurityAgent is running with increased privileges (after a sudo, unlock of System Keychain, etc). But this is not because SecurityAgent is setuid, it is because it still receives Apple Events when it runs with increased privileges. It doesn’t, however, appear to call any Apple Events functions. So I am not sure why it is processing Apple Events (handled in a base framework?). If anyone knows why, let me know.
UPDATE @ 20080705: I have poked around at this a bit more this weekend, and it turns out that an application does not need to call any Apple Events APIs in order to receive and process Apple Events. While Cocoa applications must set the NSAppleScriptEnabled property, any Carbon application automatically handles Apple Events. At the lowest level, Apple Events are sent over Mach ports looked up from the bootstrap server, so you need port send rights in order to send it Apple Events. This means that a client will not be able to send events to an application running as a different user unless it is setuid/setgid (ARDAgent) or is run with increased privileges, but still checks its ports in with the bootstrap server (SecurityAgent, which is launched by securityd with gid=0 on Tiger in certain situations).