Remote Mac Exploitation Via Custom URL Schemes

August 30 2018 by

Patrick Wardle

In recent blog posts we’ve discussed vulnerabilities or flaws in macOS that allow malicious code to perform all sorts of nefarious actions such as: bypassing SIP, approving kernel extensions, dumping the keychain and much much more! However, exploiting these flaws all require that the malicious code has (somehow) already gained initial code-execution on the targeted system. In other words they are local attacks, which generally would be used in the 2nd-stage of an offensive cyber operation.

Today, we discuss a remote attack that malware has been leveraging as a means to gain initial access to fully patched macOS systems. This 1st-stage attack, when coupled with the various aforementioned 2nd-stage attacks could create an elegant, yet damaging attack against macOS.

This attack, though remote, requires some user interaction(s).
However it has already proven successful against security conscious macOS targets. In other words, handle with care!

On August 30th, at Hack in the Box GSEC, Taha Karim (of DarkMatter, LLC), presented “The Trails of WINDSHIFT APT”. His abstract:

WINDSHIFT APT is an obscure cyber espionage actor, discovered recently targeting individuals working at a government. This actor has a dedicated and advanced spear phishing infrastructure, able to serve spear phishing emails and SMS to track individuals continuously during the reconnaissance phase, and deceiving targets during the credentials harvesting phases through the impersonation of global and local platform providers.

What makes WINDSHIFT APT different from the rest of APT actors is their sole focus on specific individuals for espionage and surveillance purposes and their very hard to attribute Modus Operandi (MO) that we will present during this talk. WINDSHIFT APT rarely engage targets with malware, Dark Matter LLC uncovered very few targeted attacks from this actor and was able to uncover and analyze the macOS malware samples used. Finally, WINDSHIFT APT have unique macOS infection tricks abusing macOS native functionalities to automatically spread malware to targets.

One of the intriguing aspects of the talk was the initial infection vector that the attackers (ab)used to successfully remotely infect Mac systems of governments somewhere in the Middle East.

My aim of this blog post isn’t to simply regurgitate Taha’s excellent talk.

Instead let’s build off it and dive a little deeper into the infection mechanism of the malware:

  • discussing some relevant macOS internals
  • provide some proof of concept code snippets
  • discuss mitigation of this remote attack

Document Handlers & URL Schemes

In a nutshell, the WINDSHIFT APT abuses custom URL schemes to remotely infect macOS targets. Although user interaction is required, it is minimal and can be “influenced” by the attacker. Moreover, the fact that this infection vector has succeeded in the wild (against government targets in the Middle East), conclusively illustrates that such interactions are not a “show stopper”.

On macOS, applications can “advertise” that they can support (or ‘handle’) various document types and/or custom URL schemes. Think of it, as an application saying, “hey if a user tries to open a document of type foo or a url with a scheme of bar I got it!” You’ve surely encountered this on macOS. For example when you double click a .pdf document is launched to handle the document. Or in a browser you click a link to an application which lives in the Mac App Store, the is launched to process that request.

Unfortunately the way Apple decided to implement (specifically, “register”) document handlers and custom URL schemes, leaves them ripe for abuse!

Though document handlers and url schemes are slightly different, from an OS point of view, they are essential the same (and thus implemented in similar manners).

Let’s first take a quick look at document handlers, as this is something I’ve researched and blogged about before.

In a previous blog post, “Click File, App Opens” I analyzed a piece of adware, Mac File Opener that abused custom document handlers as a stealthy way to achieve persistence. In short, as the malware “advertised” that it supported over 200 types of files, whenever the user opened one of these file types, the malware would be automatically launched by the OS to handle (in theory to display) the document. Persistence with a twist!

If there is already an application registered for a file type (e.g. .pdf, .html, etc), this (AFAIK) cannot be usurped.

Of course the first question was, how did the Mac File Opener adware (or any application for that matter of fact) “advertise” which files it supported (and thus should be invoked when such a documented was accessed by the user). And secondly, how does the OS process and register this information? I recommend reading the blog post as the answers to both questions are covered in great detail. But, we’ll briefly summarize it here as well.

So how does an application tell the OS what type of files it is capable of handling? The answer is in it’s Info.plist file. As noted, Mac File Opener supports over 200 file types, which we can see by dumping its Info.plist:

In the ‘raw’ plist, this information is stored in an array (key: CFBundleDocumentTypes). Apple states:

“CFBundleDocumentTypes (Array - iOS, OS X) contains an array of dictionaries that associate one or more document types with your app. Each dictionary is called a type-definition dictionary and contains keys used to define the document”

Below, we see Mac File Opener’s entry for the file type .7z (7Zip). Note the CFBundleTypeExtensions key, who’s value is set to the file extension the adware claims to handle:

 $ cat "Mac File"




To answer the second question, we need to determine how macOS handles the “registration” of these file, or “document” handlers. As noted in the “Click File, App Opens” this happens automatically! And when does this occur? As soon as the application is saved to disk! Specifically (to summarize):

  • An application (or malware) is downloaded or saved to the file system
  • This triggers an XPC message sent to the launch services daemon (lsd)
  • The lsd daemon parses the application, to extract and save its ‘document handlers’ to a persistent database.
 # fs_usage -w -f filesystem | grep Info.plist
open /Users/user/Desktop/Mac File lsd.16457
fstat64 F=4 lsd.16457
read F=4 B=0x18a97 lsd.16457

# /usr/libexec/lsd
(lldb) po $rsi
{ path = '/var/folders/np/85lyz_4545d5lz8wvy04xvlm0000gn/0//' }

We can dump lsd’s database via the lsregister (found in /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/). When invoked with the -dump flag, it will displaying all applications that specify ‘document handlers’, which were automatically registered (by lsd). For example, we can see the malicious application, Mac File Opener is present, along with the documents (file types) it registered for (e.g. .7z, etc):

 $ lsregister -dump
Container mount state: mounted
bundle id: 2592
Mach-O UUIDs: 88225C07-0FDC-3875-A3B4-C5328E509B9E, 20A99135-975D-3A7B-A8DD-B7DF2CE428D0
path: /Users/user/Downloads/Mac File
name: Mac File Opener
identifier: com.pcvark.Mac-File-Opener (0x80025f61)
executable: Contents/MacOS/Mac File Opener
claim id: 31508
 name: DocumentType
 rank: Alternate
 roles: Viewer
 flags: doc-type
 bindings: .7z

Once an application (or adware) document handers have been (automatically!) registered that application will be automatically invoked anytime a user attempts to open a document who’s type matches a registered handler.

This is handles by the launch services framework. Specifically the _LSBundleCopyOrCheckNode method (and _LSBundleCopyOrCheckNode_block_invoke) handle this lookup (of matching a document type to a registered application) and then execution of registered application:

 (lldb) b ___LSBundleCopyOrCheckNode_block_invoke
(lldb) x/gx $rdx
0x700000115c48: 0x00007fd3b4a9c520
(lldb) po 0x00007fd3b4a9c520
 { flags = 0x00000020, path = '/Users/user/Desktop/Mac File' }


  • Applications can “advertise” that they handle various documents or file types
  • The OS will automatically register those “document handlers” as soon as the app hits the disk
  • As files are opened, the “launch services” database is consulted to execute the appropriate app

Ok, so that’s “document handlers”… time to discuss custom URL scheme handlers! Again, from macOS’s point of view, such url scheme handlers, are basically just document handlers…but for urls!

Which also means custom URL scheme handlers:

  • are registered automatically by macOS as soon as application (that “advertises” support for such handlers) hits the file-system
  • will trigger the execution of the (automatically registered) handler application, when the custom url scheme is invoked

As both of these actions can be triggered from a webpage, it should be easy to see where this all goes wrong!

I’ve previously talked about custom URL schemes at Hack in the Box 2017 (see: “Oversight: Exposing Spies on macos”).

However this was this was not in the context of malware nor exploitation.

Since I don’t (yet) have access to the WINDSHIFT malware samples, I wrote my own proof of concept to illustrate how an attacker could abuse custom URL scheme handlers to remotely infect a Mac (noting again, some user interaction is required).

We start in Xcode, with the Cocoa App template:

The logic of the application is irrelevant, however we must edit the app’s Info.plist file to “advertise” that fact that we will support a custom URL scheme. In Xcode, we add a URL types array and specify the name of our scheme (windshift://) and a URL identifier:

Examining the raw plist illustrates this maps to keys such as CFBundleURLTypes CFBundleURLSchemes, and CFBundleURLName:



As soon as this application is compiled (or downloaded!) the launch services daemon will parse its bundle (specifically its Info.plist), detect the presence of the custom URL scheme handlers, and register it (them). Again, note this all happens automatically!

To confirm, dump the ‘launch services’ database (via lsregister -dump). Yups, there is our proof of concept application ( along with our custom URL scheme (CFBundleURLSchemes: (windshift)):

BundleClass: kLSBundleClassApplication
Container mount state: mounted
bundle	id: 168204
	Mach-O UUIDs: E2E77A08-F458-36C1-B7BD-99F409B4DEAC
	Device Familie
	Counterpart ID
	sequenceNum: 168204
	FamilyID: 0
	PurchaserID: 0
	DownloaderID: 0
	installType: 0
	appContainer: #
	dataContainer: #
	path: /Users/patrick/Projects/WindShift/DerivedData/WindShift/Build/Products/Debug/
	name: WindShift
	executable: Contents/MacOS/WindShift

 CFBundleURLTypes = (
 CFBundleURLName = "";
 CFBundleURLSchemes = (

claim	id: 386204
		rank: Default
		roles: Viewer
		flags: url-type
		bindings: windshift:

If we now hop over to a browser (let’s go with Safari), and “browse” to our custom URL scheme, windshift://, we can confirm that the custom url scheme was automatically registered:

If we click “Allow” (more on this alert later!), the application will be launched!

Remote Exploitation

If you’re somewhat ‘evil’ minded (or watched Taha talk!) you probably see where this is going. We’re going to now describe a method to remotely target (and ideally infect) Mac users, by (ab)using custom URL schemes.

First, the target must browse to a website we control. The WINDSHIFT APT group (successfully) used phishing emails.

Once the target visits our malicious website, we trigger the download of an archive (.zip) file that contains our malicious application. If the Mac user is using Safari, the archive will be automatically unzipped, as Apple thinks it’s wise to automatically open “safe” files. This fact is paramount, as it means the malicious application (vs. just a compressed zip archive) will now be on the user’s filesystem, which will trigger the registration of any custom URL scheme handlers! Thanks Apple!

Now that the malicious app’s custom URL scheme are registered (on the target’s system), code within the malicious webpage can load or “browse” to the custom url. This is easy to accomplish in JavaScript:


Behind the scenes macOS will lookup the handler for this custom URL scheme -which of course is our malicious application (that was just downloaded). Once this lookup is complete, the OS will kindly attempt to launch the malicious application to handle the URL request!

Luckily (for Mac users) the most recent versions of Safari this will trigger a warning:

However the characters between the quotation marks are attacker controlled, as they are the name of the application. Thus, we can easily make this popup look rather mundane, unintimidating, or even amusing:

Normally an applications cannot have a extension such as .txt or .com.

However, as the name of the application can contain unicode characters, we can leverage a homograph attack.

This allows us to name the malicious application something like Attachment.TXT (where the ‘X’ is really the Carian Letter X).

While recent versions of Safari will prompt the user before launching an the application that has been registered to handle custom URL requests, older version of Safari (e.g default install on El Capitan) do not! Instead, such versions of Safari show no warning and blindly attempt to launch the (malicious) application!

Regardless of Safari version, we have one more hurdle: File Quarantine.

File Quarantine is responsible for the popup that is displayed anytime you execute an application that is downloaded from the internet:

The good news is that some percentage of Mac users will click Cancel. The bad news is that some percentage of Mac users will click Allow (which was confirmed by Taha, who noted in his talk that the WINDSHIFT APT was successful in leveraging this attack vector).

Also, we still control the name of the application, so perhaps can increase the likelihood of users clicking ‘Allow’ … maybe by adding emojis!?

You might be wondering about Gatekeeper??

In its default configuration, Gatekeeper allows signed applications. The malware used by the WINDSHIFT APT group was signed (as is most Mac malware these days). So Gatekeeper doesn’t even come into play!

Before wrapping this all up, I made a diagram to illustrate the steps of this “custom URL scheme handler” attack:


It’s not everyday that we see APT groups targeting Mac users. And even less common does such malware leverage rather novel infection vectors. However, we’d be naive to think that Mac users are safe from such threats, as the WINDSHIFT APT group has clearly illustrated!

In this blog post we discussed features of macOS such as document handlers and custom URL scheme handlers and showed how they’re (actively) abused by malware. Luckily, such attacks (especially on modern versions of macOS) require some user interaction. However, both have proven successful in the wild.

One mitigation to this issue (if Chrome isn’t an option), is to turn off the automatic unzipping of downloaded files, as the registration of the (malicious) custom URL scheme handlers is only triggered when the application is unzipped!

To turn this off, open Safari’s preference, then in the General tab, uncheck the option Open "safe" files after downloading as highlighted here:

Also, it can’t hurt to set Gatekeeper to only allow apps from the Mac App Store, and then selectively and carefully allow external 3rd-party applications as needed!

Stay tuned for Digita’s latest product, GamePlan, offering highly flexible detection logic for a myriad of emerging behaviors and suspicious “hacking” techniques!

With GamePlan we were able to turn this blog into custom logic to generically detect/log/alert on this technique in less than 1hr! Configuration only! No new code!

Core GamePlan features include:

  • Built in objective_see-like sensors ��
  • Detection/Awareness packs curated by Digita and extended by custom user defined logic ��
  • Rapid evaluation of files, processes, system, and user actions through a native game engine, Apple’s own GamePlayKit ��
  • Enterprise Ready w/ centralized configuration, logging, SIEM support, & more! ��️

Subscribe to the Jamf Blog

Have market trends, Apple updates and Jamf news delivered directly to your inbox.

To learn more about how we collect, use, disclose, transfer, and store your information, please visit our Privacy Policy.