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.
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:
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:
LSOpenFSRef()opens a file resident on a local or remote volume
LSOpenCFURLRef()opens a URL (which could be a
file:URL, in which case it would be equivalent to a file on a volume)
LSOpenFSRef() actually calls
LSOpenFromRefSpec(), which is more general. Similarly
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:
- When the system is booted
- When a user logs in
- When the Finder "finds" a new application, such as on a newly-mounted disk image, freshly downloaded from the Internet
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...
B00000012 APPL/cssc Sat Sep 27 03:02:23 2003 ColorSyncScripting.app
-pad----hn---s--A-B- v4.2.0 ColorSync Scripting
Contents/MacOS/ColorSyncScripting 11541, 11545, Mach-O
B00000532 APPL/sfri Fri Dec 5 12:00:00 2003 Safari.app
-pad----hn---sr-A--- v125.1.0 Safari
Contents/MacOS/Safari 1466821, 2108405, Mach-O
C00000791 CSS style sheet
viewer, apple, Contents/Resources/document.icns
C00000798 Web Internet Location
viewer, apple, Contents/Resources/document.icns
C00000805 Safari download
editor, apple, Contents/Resources/download10.icns
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 most offensive and subliminal attack might work as follows:
- The attacker has a web page, possibly with multiple frames. One of the frames may show some harmless information to keep you busy.
- Another frame redirects your browser to a "
disk://..." URL, pointing to a disk image containing a bad application, say Bad.app.
- The browser downloads the disk image, which is then mounted. Bad.app would advertise itself as a handler for some non-existent URL scheme, say "
- Bad.app gets registered in the Launch Services database (automatically) as a handler for "
- There was yet another frame in the original page, with a redirect refresh time long enough to let things proceed to this point. This frame would cause a redirect to a URL of type "
- Since Launch Services knows Bad.app as a registered handler for "
arbitrary://whatever", it would simply hand control over to Bad.app, which could do whatever it wants, with the privileges of the current user.
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: URL causes (by default)
telnet to be launched within the Terminal. The
-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):
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):
A URL like the following would launch the Terminal on your computer with the specified man page:
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),
webcal: (launch iCal),
daap: (launch iTunes),
mms: (launches Windows Media Player), and so on.
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
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.