How much practical benefit is there to XPC-based privilege separation?

"Privilege separation" is one of the "two main reasons to use XPC services" given by https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html

With traditional applications, if an application becomes compromised through a buffer overflow or other security vulnerability, the attacker gains the ability to do anything that the user can do. To mitigate this risk, Mac OS X provides sandboxing—limiting what types of operations a process can perform. […] Each XPC service has its own sandbox, so XPC services can make it easier to implement proper privilege separation.

The idea (iiuc) being that if the main process is compromised, the spicier operations have been separated out to a separate process space, and this improves the security of the system.

But if the main process is compromised, and that main process is trusted by the more-privileged XPC service, is not the system still compromised in practice? That is rather than the exploit being:

  1. exploit some vulnerability
  2. gain arbitrary code execution
  3. do something naughty

isn't the same still possible with just one extra step:

  1. exploit vulnerability
  2. arbitrary execution
  3. ask the XPC service nicely…
  4. …to do something naughty?

Ahhhhh this is one of those brain loops I go on every few years. Right after posting I re-remembered at least part of the potential answer when I go down this route:

There is at least one (potential) improvement in the XPC case, because while the XPC service might be running with elevated privileges/entitlements it might not expose full access to those.

I.e. imagine an XPC service that gets installed as a system daemon to idk… delete another user's account, say. So it exposes an interface with one method, which takes the unfortunate user's name as a string and does the deed via its own root-esque privileges.

Now, if the main app is compromised the damage is at least somewhat contained. Barring a further vulnerability in the XPC daemon it can only delete user accounts. Not that that's great, but at least it can't also delete applications (barring path traversal bugs…) or reconfigure printers or install its own persistent privileged daemons….

  1. exploit vulnerability in main process
  2. arbitrary execution there
  3. pick shenanigans only from a limited menu of XPC service offerings

Is this the main/only benefit, or am I missing others?

I was about to respond in a similar fashion.

An exploit is typically considered a binary operation. The app is either secure or exploited. XPC Services make that a floating point. The app can be partially exploited, on either the main or the XPC side(s). That both limits the risk and increases the cost of the exploit.

However, then you mentioned daemons. That's something completely different. XPC is many different things. It is a communication protocol that can be used by both XPC services and daemons. But XPC services are not the same thing as daemons.

XPC services are easy to use and deploy. They give you some flexibility with sandboxing. But there's nothing easy about daemons, including The XPC communication.

There are a couple of ways XPC services can help with security. The first is the one you’re talking about, that is, where you give the XPC service elevated privileges. Your ‘delete a user’ example isn’t great though, because deleting arbitrary users is problematic and it also requires BSD privileged escalation. So let’s consider a different example.

Consider a sandboxed app that wants to install an item in ~/Library/PDF Services. There are no BSD level blocks to doing that, but it is blocked by the App Sandbox. To get around that block you sign the app with the com.apple.security.temporary-exception.files.home-relative-path.read-write temporary exception entitlement. Cool, problem solved!

Note For links to more about temporary exception entitlements, and the App Sandbox in general, see App Sandbox Resources.

However, if your app gets compromised then it might install arbitrary stuff into ~/Library/PDF Services, which isn’t great. So instead you move that code into an XPC service and the app tells the XPC service ‘install this thing’. You then only sign the XPC service with the temporary exception entitlement. Now the app can’t modify ~/Library/PDF Services; only the XPC service can. And the XPC service:

  • Acts as a bottleneck for applying policy — For example, maybe it’ll only install an PDF service that’s code signed by your team. Or a PDF service whose checksum exactly matches an allowlist.
  • Has a smaller attack surface — It’s harder for the attacker to find a hole in its code because it has a lot less code.

The second mechanism involves giving the XPC service less privileges. Imagine you have a non-sandboxed app that downloads arbitrary zip archives from the Internet and unpacks them. A malicious zip archive could exploit a buffer overrun in your code to compromise the process running that code. If that code is in your main app, that’s bad. But if you move that code to an XPC service and enable the App Sandbox on that service, that puts significant limits on what the attacker can do.


Do either of these provide perfect security? No. But they’re definitely better than nothing.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How much practical benefit is there to XPC-based privilege separation?
 
 
Q