URL-based Security Holes in Mac OS X

May 26, 2004

There has been great hue and cry over the recently found "URL exploits" in Mac OS X. I briefly looked at this issue today. While it's certainly a worrisome situation, in my opinion there seems to be more confusion than necessary (which amounts to a very normal situation in such cases!)

I have a few things to add to what has already been discussed to death in countless places. I would also try to give a summary of discussions elsewhere for the sake of completeness.

You could divide the exploits into two broad categories: one that involves a rogue application being downloaded on your machine, and another that doesn't. A specific exploit could actually belong to both categories at once.

Bad Applications

The first category needs help from the Launch Services Framework.

Launch Services Framework

The Launch Services Framework is conceptually a sub-framework of Application Services. You can find its contents under:

/System/Library/Frameworks/ApplicationServices.framework\ /Frameworks/LaunchServices.framework

Using Launch Services, you can open entities either by filesystem references, or by URL references. Launch Services provides a few functions for doing this. Consider:

Note that LSOpenFSRef() actually calls LSOpenFromRefSpec(), which is more general. Similarly LSOpenCFURLRef() calls LSOpenFromURLSpec().

Now, applications can register themselves with Launch Services: advertising their ability to open documents of a certain type (say, specified by file extension, say .insecure), or a certain URL scheme (say, arbitrary:). A key point to note here is that you usually do not have to do this registration yourself: it happens automatically, for example:

You may get a dump of the Launch Services registration database by running the command line tool lsregister (which exists in the Support/ subdirectory of LaunchServices.framework, whose path is shown above):

% lsregister -dump Checking data integrity... ...done. B00000012 APPL/cssc Sat Sep 27 03:02:23 2003 ColorSyncScripting.app -pad----hn---s--A-B- v4.2.0 ColorSync Scripting s/Resources/ColorSyncScripting.icns com.apple.ColorSyncScripting Contents/MacOS/ColorSyncScripting 11541, 11545, Mach-O V00000008 /System/Library/ScriptingAdditions/ColorSyncScripting.app ... B00000532 APPL/sfri Fri Dec 5 12:00:00 2003 Safari.app -pad----hn---sr-A--- v125.1.0 Safari Contents/Resources/compass.icns com.apple.Safari Contents/MacOS/Safari 1466821, 2108405, Mach-O V00000008 /Applications/Safari.app C00000791 CSS style sheet viewer, apple, Contents/Resources/document.icns .css, text/css C00000798 Web Internet Location viewer, apple, Contents/Resources/document.icns .webloc, 'ilht' C00000805 Safari download editor, apple, Contents/Resources/download10.icns .download ...

If you browse the output of lsregister, you can see the various MIME types, URL types, etc. that Safari wants to handle, for example.

The Attack

The most offensive and subliminal attack might work as follows:

Bad.app would claim a URL scheme by specifying it in its Info.plist file, which would exist as Bad.app/Contents/Info.plist. It would do so by specifying an array of dictionaries (named CFBundleURLTypes) describing the URL types it is able to open. Note that the bad application does not have to be ".app" style -- it could be a single file application, in which case it would advertise its abilities via a plst resource in its resource fork.

Moreover, the application can also describe an array of dictionaries (called CFBundleDocumentTypes) for the document types it can open. This introduces yet another "attack flavor" (although it requires more help from the user):

Arguably, in this case, the user "asked for it" by downloading an unknown disk image and clicking on something within. Then again, I remember popular concern over a file that "looked like an MP3", etc.

Other Nasty URL Types

Mac OS X supports numerous URL types, many of which are susceptible to mischief, without a "bad application" being downloaded on your machine. A common theme is that your clicking of a URL on a random web page causes things to happen (usually, programs to be run) on your computer.

Honestly, this is not that big a deal. If you click on a Real Media (or any other media) file, it gets played on your computer, after all. The same holds for a variety of other things. The cause for concern is that in many cases, the URL you click on can direct its handler on your system (through command line arguments) to do undesirable things.

telnet

The telnet: URL causes (by default) telnet to be launched within the Terminal. The telnet program's -n option is meant to specify a file name to which trace information would be recorded. Mac OS X passes the contents of the URL to telnet as command line arguments. Thus, the following causes /tmp/telnet.txt to be created (or worse, clobbered, if it already exists):

telnet://-n%20%2Ftmp%2Ftelnet.txt

ssh

The ssh: URL causes ssh (the client) to be launched within the Terminal. Similarly to telnet, the URL could cause the ssh client to run on your machine with specified command line arguments. For example, the command corresponding to the following URL, although harmless otherwise, should hog your CPU until killed (it reads /dev/zero for its per-user configuration file):

ssh://somehost%20-F%20%2Fdev%2Fzero

x-man-page

A URL like the following would launch the Terminal on your computer with the specified man page:

x-man-page://emacs

Numerous other URL types existing in random web pages would cause applications to run on your machine. Even though this is how it's supposed to work, unless the mechanism is foolproof, it could be a nuisance, or worse. Apple needs to ensure that these applications cannot be made to do undesirable things through URLs. Examples of such URLs include addressbook: (launches the Address Book), ical: and webcal: (launch iCal), itms:, itmss:, and daap: (launch iTunes), mms: (launches Windows Media Player), and so on.

Solution

While Apple needs to fix plenty of things (the fact that command line arguments are being passed to applications through URLs, for instance), the Launch Services issue is as much of a policy problem as a technical problem.

If a solution involves the user as a mediator, that is, the entity performing admission control of some kind, one needs to figure out if it's better to ask the user every time Launch Services "launches" a URL of a type marked as unsafe or unknown, or if it's better to ask the question at registration time.

An interim solution (which I am guessing is what one or more of the solutions out there do) would be to intercept LSOpenFromURLSpec() and LSOpenFromRefSpec(), because they figure in the code-paths that eventually open any document or URL types. These functions are implemented in the LaunchServices shared library (which is dynamically linked). On Linux, for example, one could use LD_PRELOAD in a situation like this. The closest thing to LD_PRELOAD on Mac OS X is DYLD_INSERT_LIBRARIES, but it would not work with two-level namespaces. Other alternatives include altering the binary (of the library), or its runtime image, to re-route invocations of the above functions to our own implementations that do admission control (possibly interactive) of each URL type, etc., encountered.

What about "hijacking"?

One could wonder what happens if a rogue (or even otherwise) application wants to handle a document or URL type that is already registered in the Launch Services database.

Launch Services considers several things before deciding the winning candidate. A handler explicitly specified by the user takes the highest precedence. More importantly, an application on the boot volume is preferred over applications on any other volumes. Similarly, an application on local volume is preferred over those on remote volumes. For details of this process (and other criteria for selecting a candidate), refer to Apple's Launch Services documentation.