Bypassing OS X Gatekeeper (CVE-2014-8826)

On January 27, 2015, posted by hernan

Today we published a security advisory for a vulnerability that allows attackers to bypass OS X Gatekeeper and execute unsigned arbitrary code downloaded by the user, if the user has Java installed on his machine (although Java is not causing the vulnerability); for more information see

When Apple released its security update for Shellshock on Sep 29 2014, I mentioned I was surprised to see Apple distributing the update as a manual update instead of using the Software Update mechanism. I also mentioned distributing the manual update as a signed package inside a DMG (Disk Image) file over HTTP was not the best option, it would have been better to distribute it over HTTPS. Especially for a extremely critical vulnerability as Shellshock.

I understand code signing offers protection against tampering/man-in-the-middle attacks, of course; but the process seems fragile: the user downloads a .DMG file from a HTTP link (vulnerable to MiTM attacks), opens the DMG file, a new volume is mounted, the user sees the file BashUpdateMavericks.pkg, which basically can be anything, double-clicks the file, OS X Gatekeeper verifies the package, and if everything is ok, the code is executed.

There are too many (unnecessarily created in my opinion) possible attack scenarios within this process: the user downloads a DMG file from an insecure link that can be intercepted, before the .pkg inside the Disk Image is verified by OS X Gatekeeper (this happens when you double-click the .pkg file) the user has already mounted a potentially malicious DMG file which could exploit vulnerabilities affecting the handling/parsing/mounting mechanism, Disk Image files support 'customization' options that can have vulnerabilities, for example, they can have a background image, etc, etc.

This is not the best process to install a security update in my opinion, using the Software Update mechanism is better (also because it is a "push" mechanism); and using a secure channel (HTTPS) to distribute security updates adds another layer of protection and potentially closes an attack scenario otherwise possible.

This motivated me to try to find a way to bypass OS X Gatekeeper; I began with the most basic and simple tests and I didn't have to go any further because I found a trivial way to execute (unsigned) Java code bypassing Gatekeeper (from a technical standpoint, there's of course a universe of more interesting and complex attack scenarios left to research around OS X Gatekeeper).

The attack is not 'perfect' in the sense it requires the victim to have Java installed, which is not installed by default; which means regular users are not likely to be affected.

However, many companies and developers use Java on their Macs every day, and they are definitely an interesting target for attackers because of the kind of information they handle (e.g. source code).

As explained in the advisory, exploitation, again, is trivial. Let's see:

arrow Create a .class file with the following code:


public class AmpliaTest {
public static void main(String[] args) {
try { Runtime.getRuntime().exec("/usr/bin/touch /tmp/AMPLIASECURITY"); } catch(Exception e) { }

arrow Host AmpliaTest.class in a web server
arrow Download the file with Safari (the file is saved to the downloads folder automatically, the user is not prompted before the file is saved)
arrow In Finder, double-click the file. The code is not executed and the following message is displayed:

arrow Now create a Jar file:

$ echo "main-class: AmpliaTest" > Manifest

$ jar cmf Manifest UnsignedCode.jar AmpliaTest.class

arrow Copy UnsignedCode.jar to the web server
arrow Download the file with Safari (again, it is saved automatically, no prompt)
arrow Double-click the file. The code is not executed and the same message shown before is displayed:

arrow On the web server, copy AmpliaTest.class to AmpliaTest
arrow Download the file with Safari
arrow In Finder, double-click the file. The code, again, is not executed:

arrow On the web server, copy UnsignedCode.jar to UnsignedCode
arrow Download the file with Safari
arrow Because the .jar file has no extension, Safari handles it as a ZIP file and uncompress it. With Finder, go to your downloads folder and you'll see a folder named 'UnsignedCode', inside you will find the contents of the Jar file:

arrow Double-Click on AmpliaTest.class, and the code will not be executed (the same message as before is displayed)

arrow Now, create a DMG file

$ hdiutil create -size 5m -fs HFS+ -volname AmpliaSecurity AmpliaTest.dmg

arrow Mount the disk image, copy UnsignedCode.jar to the AmpliaSecurity volume, unmount the disk image, copy AmpliaTest.dmg to the web server
arrow Download AmpliaTest.dmg with Safari
arrow Mount the Disk Image
arrow Double-Click on UnsignedCode.jar. The code will not be executed:

arrow Finally, delete the DMG file, create a new one, copy UnsignedCode (with no extension) to the mounted volume, unmount, copy AmpliaTest.dmg to the web server
arrow Download AmpliaTest.dmg with Safari
arrow Mount the Disk Image
arrow Double-Click on UnsignedCode

arrow The code will be executed, bypassing OS X Gatekeeper
arrow In this example, the code executed creates the file /tmp/AMPLIASECURITY

arrow Perform the same tests performed before for the .class and .jar files with Firefox. Firefox prompts the user before downloading the code. The code will not be executed.
arrow With Firefox, download UnsignedCode (the Jar file without extension). Firefox prompts the user but the Jar file is identified as a Text file (the same happens for .class files with no extension and jar files with no extension inside Disk images downloaded with Safari), and contrary to what Safari does, the file is not uncompressed :

arrow Double-Click on UnsignedCode, and the code will be executed bypassing OS X Gatekeeper
arrow In this case, there is no need to create the DMG Disk Image