Monday, September 2, 2019

PrivilegedHelperTools and Checking XPC Peers

Objective Development:

It all began with a security improvement by Apple in macOS High Sierra (10.13). Apple had revoked access to the folder /Library/Logs/DiagnosticReports for non-admin users. The protection goes so far that even a root process spawned by AuthorizationExecuteWithPrivileges() cannot access the folder.

[…]

Every installer application which needs root permissions is now urged to install a system-wide daemon for this purpose. This system-wide daemon is usually left behind, because Apple provides no API for removing it.

[…]

In an internal code review, another developer looked over the code and verified all assumptions. He did not find a proof for the assumption that XPC connections are authorized by the system. Since there was little information available, he made a test project and could exploit our privileged helper tool!

[…]

The helper (and the app using the helper) should check the identity of the peer before performing any operations. Even if an AuthorizationExternalForm is already used. The most secure way for such a check is the code signature.

[…]

Note that this example uses the private NSXPCConnection.auditToken property. If we want to avoid using a private property, we need to use the Unix process ID. But this is inherently insecure (see Don’t trust the PID! by Samuel Groß). We therefore decided to use auditToken anyway.

So, because Apple decided to protect the logs folder, and the documentation is not very good, the Little Snitch developers ended up introducing a privilege escalation vulnerability, and even now they can’t make it fully secure without using private API. These are smart developers with a long history building a highly regarded security-focused product. Of course it sounds like a good idea to make the logs secure, but I think we can ask whether it was worth the cost in collateral security and engineering time. And why should it be so difficult and error-prone for an app to facilitate the customer sending in a diagnostic report?

See also: CVE-2019-13013.

Joe Auricchio (in 2016, via Jeff Johnson):

It’s better to keep using the deprecated SM functions than to run launchctl. Sorry, but replacements are not yet available.

There isn’t presently API for a system-wide LaunchDaemon to open a Mach IPC or XPC connection to a LaunchAgent, which I’d guess is closer to what you’d really like to do? This would be a good enhancement request, please file one!

10 Comments RSS · Twitter

I think it's worth repeating their final advice to Mac users, I found a bunch of old helpers on my Mac:

So we highly recommend all Mac users to review the contents of their /Library/PrivilegedHelperTools folder in Finder to watch for installed helper tools and to delete those that are obviously no longer needed (the helper’s name often gives a hint about the corresponding app and its purpose).

If you are not sure about a particular helper, it may even be advisable to remove one helper too much (assuming that the app will reinstall it anyway, if needed) rather than leave a possible vulnerability on your Mac.

"It all began with a security improvement by Apple in macOS High Sierra (10.13). Apple had revoked access to the folder /Library/Logs/DiagnosticReports for non-admin users.”

As far as I know, standard users have never had access to /Library/Logs/DiagnosticReports. At least, they didn’t in Mavericks. I don’t have any older VMs handy to check anything before that, but I’m pretty sure this is really old, perhaps original, behaviour.

"This system-wide daemon is usually left behind, because Apple provides no API for removing it.”

Apple has no API for uninstallations of any kind. The barest minimum of uninstaller support comes in the Mac App Store. Otherwise, it has always been the developer’s responsibility to uninstall any software, including anything in /Library/PrivilegedHelpers.

"There’s another issue with the SMJobBless() API: It is not well documented.”

Apple’s “Secure Coding Guide” goes into great detail about privileges, authorization, and the details of securely communicating with privileged helpers. This document has been updated along with Apple’s best practices for authorization and security, but was first published in 2006.

And finally, "We’ve now disclosed the technical details of a severe security issue on the Mac that also affected Little Snitch”

This is not a Mac issue. It is only a Little Snitch issue. This is one of the risks with writing and using software that runs with elevated privileges. You put your reputation and your users at risk.

@John Daniel

Apple has no API for uninstallations of any kind.

This is a special situation because the file is installed and managed by the OS. The app doesn’t necessarily know where it’s being installed, or have access to uninstall it, or know whether it’s still in use. So it makes sense that the OS should also manage cleaning it up.

Apple’s “Secure Coding Guide” goes into great detail about privileges, authorization, and the details of securely communicating with privileged helpers.

As far as I can tell, that document doesn’t mention SMJobBless() or checking the code signing identity. The SMJobBless documentation doesn’t either. Neither links to any sample code. The newest sample code seems to be EvenBetterAuthorizationSample, which superseded BetterAuthorizationSample. Neither sample code project shows up when searching Apple’s site for their names or for SMJobBless. EvenBetterAuthorizationSample was last modified in 2013, says it requires Xcode 4, and is part of the documentation archive—so it’s no longer being updated. And even if you somehow find it, it doesn’t demonstrate checking the code signing requirement.

This is not a Mac issue. It is only a Little Snitch issue.

You really think every other app that uses SMJobBless() does this right?

@John Daniel

I'm a bit dubitative about the quality of the Apple documentation and example. For instance the SMJobLess example has a terrible workflow to build the app. Which makes going with other solutions (maybe not as good or as secure) more enticing.

Sören Nils Kuklau

So we highly recommend all Mac users to review the contents of their /Library/PrivilegedHelperTools folder in Finder to watch for installed helper tools and to delete those that are obviously no longer needed

I get that Apple neither wanted the Windows-esque notion of “uninstallers” nor the Linux-esque hardcore approach of an end-user packet manager when designing Mac OS X, but having stray files left behind when moving an app to the trash was always a peculiar design weakness.

There have been various hacks to work around it (like a background task that watches for you trashing apps, then asks if you want to remove likely satellite files as well), but it seems odd that Apple never addressed this through a formal solution. It’s one thing to have that with old preferences files and caches, but it’s another once you add privacy and security risks with stray PrivilegedHelperTools.

Imagine, for example, an AppAssociatedSatelliteFiles key in the app’s Info.plist that simply supports a glob syntax. Delete the app, and those files get deleted as well. (Maybe this risks deleting files the app isn’t actually supposed to own? This is why Apple doesn’t pay me the big bucks.)

@Michael,
It’s a “privileged” helper tool. It can do anything it wants, including uninstalling itself.

I’m not arguing that 3rd party software should be required to manage installations and uninstallation. The way it works (or, rather, doesn’t) on the Mac is just awful. When I used to write Windows software I always used Inno Setup. It made installations and uninstallation a pleasure. It is that good. It’s just a shame that Macs in 2019 are so far behind Windows from over two decades ago. That being said, this shouldn’t be news to developers. If a developer screws it up, they should just fess up and admit it. Everybody screws up every now and then. That’s no big deal. But it looks bad when you try to blame your screw ups on others.

Privileged operations are similar to kernel extensions. Apple has made a conscious effort to make them more difficult over the years. Apple says it is to make the OS more secure, but that’s not really true. Apple wants to make the OS more reliable. One of the primary sources of Mac problems (problems that Apple has to deal with) are developers hacking around on privileged apps and kernel extensions. If Apple wanted developers to do this, they would setup an “Everybody can elevate privileges safely” web site and maybe mention it at WWDC. That being said, there is nothing to stop a developer from asking about this topic at WWDC or submitting a DTS ticket about it.

I only used the word “only” in a binary sense, comparing Apple to Little Snitch. I don’t know how other apps do it. I’ve only looked into how one popular app does it and they also do it horribly wrong. I don’t know. Which is worse? To blame one errors on others or to refuse to admit to any?

@John Daniel Well, the first paragraph says they “shipped a version of Little Snitch with a serious vulnerability” and that they are trying to “learn from it,” and it was their “misunderstanding.” So it seems like they are accepting some blame. I do think Apple deserves some as well, though, because getting this right is hard and not documented well.

I spent many days trying to add a privileged helper with XPC to my (non-sandboxed) app Find Any File.

I found EvenBetterAuthorizationSample, which comes with a script that shows me the special strings I have to add to both the main and helper apps' Info.plist files (such as "SMAuthorizedClients"). If I had those wrong, the blessing or connection (can't remember which) would not work.

So I had assumed that these strings, which contain some signature data about both executables, would ensure that the OS checks that no other app could talk to my helper, and that it would not load it if someone modified it (after the signature-check by macOS) before it got blessed (i.e. I'd expect that, to prevent such a hack, the OS would again check the codesigning right when it would move the code to the secured root folder, making sure no one messed with the code).

But this article suggests that all this is not ensured, and instead I have to double check both the identify and the signature of the calling app myself. With no code sample given by Apple. I am so confused and feel so helpless as I cannot ever understand how to figure out whenever I'd got it right or not.

@Kentzo I posted about that here.

Leave a Comment