-
Re: XPC restricted to processes with the same code signing?
eskimo Feb 21, 2017 1:21 AM (in response to jasosimm)1 of 1 people found this helpfulCan one restrict XPC communications to only occur between processes that share the same code signing identity?
Yes. Well, you probably don’t want the same core signing identity (in general, each separate executable should have its own identity) but rather you want to evaluate code signing requirements for the client, and you can definitely do that. There are two basic tools for this:
Various properties on the XPC connection (like NSXPCConnection’s
auditSessionIdentifier
,processIdentifier
,effectiveUserIdentifier
, andeffectiveGroupIdentifier
properties, and the equivalent C functions to get these values from anxpc_connection_t
)Various security APIs, most notably the code signing API (
<Security/SecCode.h>
)
The exact way in which you combine these is up to you, but here’s an example of how you might restrict access to your service to just your app:
When a client makes a connection to your service, get the process ID of the client from that connection. If you’re using NSXPCConnection, you should do this in your
-listener:shouldAcceptNewConnection:
delegate callback. If you’re using the lower-level XPC C API, you’d should do this in the event handler for your listener connection.Use that process ID to create a code object for that client (
SecCodeCopyGuestWithAttributes
withkSecGuestAttributePid
).Create a requirement object that describes the clients you’d want to allow to connect (typically using
SecRequirementCreateWithData
but also see the note below).Check that the code object from step 2 meets the requirement from step 3 (
SecCodeCheckValidity
orSecCodeCheckValidityWithErrors
).
There’s a couple of potential security gotchas here. I’ll discuss those below, but first I want to make a few ancillary points:
In step 3, you can prepare the requirement object up front, so you don’t need to create it anew for each connection.
Again in step 3, you can create your requirement object using either
SecRequirementCreateWithData
orSecRequirementCreateWithString
. If you use the former, you can pre-compile the requirement data usingcsreq
.It’s seems pretty obvious that the system should provide better support for XPC service access control. In fact, it does provide better support for this, it’s just that this support is all private. I encourage you to file an enhancement request describing your high-level goạls, what you had to do to achieve them, and how you’d like to see the system improved to make things easier. Please post your bug number, just for the record.
The first potential security gotcha relates to the security of the client app itself. If your client app loads any code (like plug-ins), that code will have the same access as the app’s main code. This could completely undermine the security of the system as a whole.
The best solution to this problem is to turn on library validation for your app. This is a code signing feature that ensures that your app can only load ‘blessed’ code. I’m not an expert in library validation but you can get started by looking at the
library
option described in thecodesign
man page.The second issue relates to the process ID. The OS’s process ID space is relatively small, which means that process IDs are commonly reused. Thus, it’s a bad idea to use a process ID in security-related work.
There is a recommended alternative to process IDs, namely audit tokens (
audit_token_t
), but you can’t use this because a critical piece of public API is missing. While you can do step 2 with an audit token (usingkSecGuestAttributeAudit
), there’s no public API to get an audit token from an XPC connection (step 1)-:If you’d like to switch over to audit tokens then, again, I recommend you file an enhancement request for this facility to be made public.
Fortunately, process ID wrapping problems aren’t a real threat in this context because, if you create an XPC connection per process, you can do your checking based on the process ID of that process. If the process dies, the connection goes away and you’ll end up rechecking the process ID on the new connection.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
Re: XPC restricted to processes with the same code signing?
jasosimm Feb 21, 2017 9:11 AM (in response to eskimo)Thank you for the in depth answer. Very helpful.
-
Re: XPC restricted to processes with the same code signing?
Coder256 Dec 27, 2017 12:12 PM (in response to eskimo)Fortunately, process ID wrapping problems aren’t a real threat in this context because, if you create an XPC connection per process, you can do your checking based on the process ID of that process. If the process dies, the connection goes away and you’ll end up rechecking the process ID on the new connection.
I would rather not rely on the connection being invalidated just because the client process exits. Especially given that Apple has started switching from PIDs to audit tokens, which is demonstrated by WebKit bug 170616, and more importantly its corresponding changeset 215132, both of which were created by an Apple employee. In fact, it appears that they have started validation using audit tokens in more than just WebKit - even SystemAdministration.framework checks the audit token (and it's already obsolete!). My point is that Apple already internally does the checking you describe, but has still SPI'd the audit token in both the C and Objective-C XPC interfaces (
xpc_connection_get_audit_token
andNSXPCConnection.auditToken
respectively).It is not clear why they do this; the audit token contains only useful but not sensitive information: the sender's audit UID, effective/real UID/GID, PID, audit session ID, and PID version, used for when the PID wraps around (reference:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/bsm/libbsm.h
, the online versions are out of date). Most of that information could be inferred anyway based on the PID and effective UID/GID already provided.There's really no reason to conceal the audit token. Its only purpose since its creation is for security verification, and that was back in 2004 before GateKeeper, and before even File Quarantine (reference:
man au_token
). As its name suggests, it is meant for security auditing and is not a security risk if exposed. There is no reason why this additional protection should be restricted from developers, because the only difference it would make is that their apps would have the option of increased security.How do you file an enhancement request in the new bug reporter?
-
Re: XPC restricted to processes with the same code signing?
fumoboy007 Dec 12, 2018 4:22 PM (in response to Coder256)@eskimo @Coder256 How does the audit token relate to the audit session identifier? NSXPCConnection.auditSessionIdentifier has been available since macOS 10.8. Can we use that to authenticate the sender? If so, how?
-
Re: XPC restricted to processes with the same code signing?
eskimo Dec 13, 2018 2:26 AM (in response to fumoboy007)How does the audit token relate to the audit session identifier?
This audit session identifiers identies the login session, which isn’t really helpful in this context.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
-
Re: XPC restricted to processes with the same code signing?
eskimo Dec 13, 2018 2:24 AM (in response to Coder256)[Hmmm, I seem to have missed your post last year, possibly due to the Apple’s winter shutdown. Oh well, better never than late.]
I would rather not rely on the connection being invalidated just because the client process exits.
I absolutely agree with you there.
How do you file an enhancement request in the new bug reporter?
You should be as simple as setting the Classification to Enhancement Request.
Did you get a bug filed about this? If so, what was the bug number?
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-