XPC restricted to processes with the same code signing?

Apple Recommended

Replies

Could you elaborate what is implied by


> has been processed


Is it processed by the time user's callback is entered or exited?


> Once the first message has been processed, the connection is established such that my “if the process terminates, the connection goes with it” logic kicks in.


Isn't it possible for an originating process to die and wrap while XPC service is still within user's callback for the 2nd message?

Isn't it possible for an originating process to die and wrap while XPC service is still within user's callback for the 2nd message?

Absolutely. But, by the time of the second message, the XPC connection is fully established, so there’s no way for a replacement process to send a message down that same connection.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

While the OS ensures that the second message can only be sent by the same process that sent the first message, it alone is not enough for user's code in the XPC service.


Thus it seems important for user's code in the XPC service to:

1. When handling the first message capture process's identity (in terms of requirements, version, code signature etc) and avoid performing any priviliged actions. In other words let the first message be a handshake.

2. When handling all consequent messages use the identity captured in [1] for permissions check before performing any priviliged actions


At least it appears to be enough if permissions checks are run against code signature and backed-in data (such as requirements) which is also reflected by the signature.


Is my understanding more-or-less in line with what you have suggested above?

Quinn,


My apologies by I seem to miss something obvious here. In this reply you suggested two paths:


1. Use a private API to acquire the audit token of an XPC connection

2. Use PID but rely on that 2nd and forth messages are guaranteed to come from the same connection


While [1] is quite clear I'm completly puzzled by [2].


Which of the following do you suggest:


1. Run peer validation pased on code object created from a PID associated with the connection upon receiving the first message, then, if successful, mark that connection authenticated and perform priviliged work starting with the 2nd message

2. Same as [1] but re-validate the peer for each message

3. Something else


---


The scenario I have in mind is:


1. Malicious process starts, sends 2 messages

2. The system does whaterver it does, processes the messages and enques them for delivery to user's code

3. Malicious process through other means (e.g. timing?) figures out that its messages were enqued for delivery and initiates wrapping

4. Legitimate process takes its places

5. Enqueued messages finally reach user's code. User acquires PID, gets code object of the Legitimate process and responds to the messages. Since both message are already enqueued user has no chance (aside from using private API to get auditToken) to recognize malicious intent.


To avoid the attack, as I understand, the OS must not bulk process messages. Instead it should process them one by one, only picking the next message after user's code is done with the previous one.


In the scenario above it would force the peer to be around up until the moment the 2nd message was passed to user's code. Thus preventing the wrap.


Please guide me!

After spending a while trying to figure the best approach for this problem, I eventually settled on using the XPC C API which allows for securing the connection using the SecCodeCreateWithXPCMessage function on macOS 11 and later, and falling back to using a private function on older versions. But I didn't want to have to directly use the C API all throughout my codebase so I created the SecureXPC framework in Swift. Hopefully this is helpful to some people here. Feedback is most welcome on the Github page either as issues or discussions!

  • Thanks for sharing!

Add a Comment