This and the next few posts are full `geek_mode=on' posts. Sorry.
Safari / Dashboard vulnerability in OS X 10.4
This page discusses a security flaw resulting from a series of bad design choices in Safari and Dashboard in OS X 10.4, and links to a demonstration exploit.
You can make your machine safe by unchecking the ``automatically open `safe' files" option in Safari:
- Update: Mac OS X 10.4.1 fixes this vulnerability, by changing Safari to present a dialog when downloading all widgets. Kudos to Apple for their speedy response to the issue.
- Updated May 10 with a new, simpler, more deadly exploit.
1. Widget Auto-Install
Safari 2.0 in Mac OS X 10.4 Tiger has a dangerous new ``feature". By default, when asked to download a .zipped Dashboard widget, Safari not only unzips the widget, but also copies the widget into ~/Library/Widgets, and adds it to your Dashboard Bar. As first pointed out by Stephan.com, Safari does this not only for widgets you explicitly click on, but also for widgets that are silently, automatically downloaded by a web page's META refresh tag. So a malicious website can auto-install potentially malicious widgets without you even realizing the installation happened.
This is the rough equivalent of automatically installing auto-downloaded applications into the /Applications/ folder, and putting them on the Dock.
2. The Evil Twin
Apple's second major mistake in Dashboard is in how widgets are loaded.
First, it is important to emphasize that the auto-installed widgets do not execute automatically. It remains a `social engineering' task for a malicious attacker to get you to launch with widget by dragging it from your Dashboard Bar.
However, this is aided by Apple's second incredibly bad design decision. Widgets are identified by a `bundle identifier', such as com.apple.widget.stickies. When Dashboard encounters two or more widgets with the same bundle identifier, it only displays the last one loaded. And -- you guessed it -- widgets in ~/Library/Widgets are loaded after the system-supplied widgets in /Library/Widgets.
This means that our malicious widget can completely replace an Apple-supplied widget. Your ordinary Stickies widget simply will not appear in the Dashboard Bar -- but in its place, silently installed by Safari, is a malicious widget.
For example, here is the Dashboard Bar before visiting a malicious web page:
And here it is afterwards:
Can you tell the difference? If you can't, and try to create a new Sticky note...
...you have just launched a malicious program.
Note: It appears that an additional, unrelated bug in Dashboard may actually be a saving grace here. After ~/Library/Widgets has been updated, Dashboard sometimes garbles the contents of the Dashboard Bar, so when you try to drag a widget from the Bar, you get no widget, or an entirely different widget. Scrolling between pages of the bar resolves the issue. Nonetheless, your original safe Stickies is now gone, with a malicious one in its place.
3. The Sandbox That Isn't
And now we come to Apple's third major mistake. Apple went to great lengths to develop a security model for Dashboard widgets. By default, Widgets do not have access to local files, your network connection, or the ability to run native code, other than opening applicications and web pages.
Widgets can request additional privileges, including the ability to run arbitrary shell commands with the widget.system() call. The first time you double-click to run a widget that requests extra privileges, in most cases Dashboard presents an `are you sure?' prompt before allowing it to run.
Ought to appear, but does not.
However -- incredibly, amazingly, stupidly -- Dashboard does not present a prompt before running a privileged widget that is one of the Library/Widgets folders, including our auto-installed widgets. So now your auto-installed replacement look-alike widget has complete access to your system, and could do nasty things like delete your home folder.
If a widget contains a native Mach-O executable, Safari will present a warning before downloading the widget. However, because widgets in ~/Library/Widgets can run shell commands with the widget.system() call, this protection is easily defeated. The demonstration exploit below includes a native Mach-O application with its bits reversed, so Safari does not realize it's an application. A call to a Perl script unreverses the bits and makes the file executable, allowing full native code to be run.
Or, in a self-propagating attack, the widget could start a user-level Apache (on a user-accessible port like 8080), and email everyone in your addressbook with the URL to visit. They need only click on the URL to install the widget on their own Macs running Tiger, etc. etc.
4. Privilege Escalation
Our malicious widget has all of the capabilities of an ordinary application launched by your user. This is bad enough, but it could also take advantage of privilege escalation vulnerabilities to run as root, where the damage could be more widespread. If the widget acquired root it could, for example, start Apache for you and proceed as described above in the self-propagation.
One such privilege escalation that is known to work on Tiger is this sudo-piggyback method, in which the widget waits silently in the background for an admin user to run sudo, then piggy-backs onto the sudo grace period and acquires root. I'm sure there are a few other buffer-overflow vulnerabilities lying around.
WARNING! This example exploit page will:
1. download a single .zip file
2. In Safari on OS X 10.4, auto-install a Stickies widget to your Dashboard Bar that replaces the Apple-supplied widget.
3. Upon dragging the `Evil Stickies' widget out of the Dashboard Bar, request (and receive) full system access, unpacks a binary executable, and runs a Perl script to speak some greetings.
I have received feedback that due to an unrelated Dashboard bug, you might have to scroll the Dashboard Bar once or twice before you can drag new widgets from it.
None of these widgets does anything actually malicious. (My school would kill me if I were distributing malware from their servers :-)
To get rid of the evil `Stickies' widget, simply go to ~/Library/Widgets, and delete the widget named `Stickies.wdgt'. It will be gone -- and the normal Apple widget back again -- the next time you invoke the Dashboard.
If and only if you understand those removal instructions, you may now try the example exploit:
I'd appreciate feedback on how these widgets behaved on your system. Did the Stickies widget require confirmation to run? Did the widget displace the Apple one from your Dashboard Bar?
Please write with comments to firstname.lastname@example.org. Thanks.