PR is all about attitude manipulation.


Multiple binaries inside the /Applications directory tree are setuid root, but remain writable by users in the admin group (ex. first user by default in a non-server Mac OS X installation), allowing privilege escalation. A malicious user can overwrite the binaries and perform a disk permissions repair operation via the diskutil tool, effectively setting back the default ownership and permissions (root setuid).

The following is a list of the few different binaries that can be used to escalate privileges:

/Applications/Utilities/Activity /Applications/Utilities/Keychain /Applications/Utilities/ODBC

Affected versions

Mac OS X 10.4.8 (8L2127). Previous versions should be affected if the binaries exist in the mentioned paths. This issue is architecture independent.

Proof of concept, exploit or instructions to reproduce

The provided exploit will replace one of the affected binaries with a wrapper, spawning a shell with root privileges when executed:

aunt-sophias-computer:~/ pwner$ ruby MOAB-15-01-2007.rb 
++ Starting: /Applications/Utilities/Activity
++ Back-up:  /tmp/pmTool
++ Compiling a shell wrapper at /tmp/o...
++ Placing backdoor...
Started verify/repair permissions on disk disk0s2 Macintosh HD
Determining correct file permissions.
parent directory ./Users/Shared/SC Info does not exist
User differs on (...)/pmTool, should be 0, owner is 501
Group differs on (...)/pmTool, should be 80, group is 0
Permissions differ on (...)/pmTool, should be -rwsrwxr-x , they are -rwxr-xr-x 
Owner and group corrected on (...)/pmTool
Permissions corrected on (...)/pmTool
The privileges have been verified or repaired on the selected volume
Verify/repair finished permissions on disk disk0s2 Macintosh HD
++ Finished. Backup at /tmp/pmTool.
++ Repair with: mv '/tmp/pmTool' '(...)/pmTool'
++ Enjoy root shell.
$ '/Applications/Utilities/Activity'
sh-2.05b# id
uid=0(root) gid=0(wheel) groups=0(wheel), 81(appserveradm), 79(appserverusr), 80(admin)
sh-2.05b# exit
aunt-sophias-computer:~/ pwner$ id
uid=501(pwner) gid=501(pwner) groups=501(pwner), 81(appserveradm), 79(appserverusr),

Original files will be copied at /tmp, simply move them over the backdoor path for repairing the old file.

Debugging information

The original permissions and ownership set in the binaries:

-rwsrwxr-x   1 root  admin  13268 Jan 15 16:58 /Applications/.../pmTool
-rwsrwxr-x   1 root  admin  61040 Jan 27  2006 /Applications/.../kcproxy
-rwsrwxr-x   1 root  admin  51820 Jan 14  2006 /Applications/.../iodbcadmintool

The diskutil tool will set these permissions every-time a 'repair permissions' operation is being done.


Exploitation conditions

Privileges for overwriting the files under /Applications are necessary (ex. users in the admin group are allowed to do it, and every default first user of a non-server Mac OS X environment belongs to it). Once the malicious file has been installed, running diskutil is necessary for setting the rogue permissions back (setuid bit, executable, owned by root):

$ diskutil repairPermissions /

Again, diskutil won't perform validation of permissions and ownership. Apparently, for Apple (and Unsanity LLC too) "engineers", it's the right thing to put a binary being executed with root privileges or having the setuid bit (and owned by root) at an user writable path.

Applied concept for malware on Mac OS X

At this point, we have observed the use of flawed permissions and the deployment of a tool (diskutil) by Apple which opens OS X to the most simple privilege escalation issues. It's repair permissions functionality is not only flawed by design but also commonly referred as a 'solution' (normally recommended by Apple's tech support) to almost every 'non text book' problem reported by end-users.

It's integration in the system and the presence of a vulnerable permissions 'tree' (that is, allowing users belonging to a certain group for installing application bundles, input managers, hooking every Cocoa application, etc...) opens the OS X to a more sophisticated malware class.

The idea of a simple companion-style infector is nothing new, although, the idea of an infector that attempts to escalate privileges in an automated fashion is certainly innovative. Basically, the infection process would involve a permission check, a privileges check (what's our effective uid? and group?) and then the proper companion method (briefly described later) plus a last check and execution of the diskutil tool. The goal? If we infect a file we have write access to, and it happens to be set by diskutil as root owned and setuid later, execution of that file will run the infector with root privileges, effectively compromising the whole system. Without requiring the root user or anyone else to get 'tricked' into executing any binary. The infector would continue running binaries, setting new privileges over them.


This past weekend, we (Gil Dabah, aka Arkon - LMH) started working on a proof of concept deploying this concept, in pure x86 assembly. We intend to release it first to AV companies, before public distribution. Arkon proposed a nice method for the 'companion': instead of the usual "append" technique (which won't work with fat binaries), the binary would 'pack' the host, placing itself in the start of the file, and when executed, it will decompress it to the temporary directory, then executing it with the passed arguments and environment. This won't help, at all, to prevent detection by AV engines but it's not our goal to produce a potentially harmful tool. Another issue is performance, and avoiding infinite recursion (ex. trying to infect the binary twice). For preventing the latter, we can just seek for a signature / sequence of bytes in the file. Performance can be improved if we limit the number of infections 'per iteration'.

The code base is mostly ready, thus we expect to release it soon, after some testing and optimization work.

Workaround or temporary solution

For preventing usage of diskutil to achieve this and similar privilege escalation attacks, remove the setuid bit from /System/Library/PrivateFrameworks/DiskManagement.framework/Resources/DiskManagementTool.

$ sudo chmod -s (...)/Resources/DiskManagementTool

Also, verify that none of these files have been replaced (compare SHA-1 hash to a pristine installation) or tampered in some manner, as well as removing any rogue permissions: