In my last article, I gave an introduction to Apple's Transparency, Consent, and Control (TCC) framework. The primary goal of TCC is to empower users with transparency regarding how their data is accessed and used by applications. This time around, we're going to dig deeper into the mechanism that runs TCC and what's going on in the background.
The Primary Framework
TCC is managed by a [.highlight]tccd[.highlight] binary in the System directory, at [.highlight]/System/Library/PrivateFrameworks/TCC.framework/Support/tccd[.highlight]. It’s worth noting, that formerly, this binary was located within the /Versions/A/ directory in the [.highlight].framework[.highlight] bundle but has since moved.
There is one aspect of TCC parlance that I want to cover before we dive too deep. We will be primarily talking about two () when we speak about the TCC framework—we'll often discuss a client and a service. In this case, the client is the application that’s requesting permission, such as Zoom, whereas the service is the permission it is requesting, such as camera or microphone access. The client is requesting access to a service.
If we dump the strings from this binary, we can see the different services that TCC covers, although their names are not necessarily straightforward.
When we look in our TCC databases, one of the columns we'll see is [.highlight]service[.highlight]. Within this service field, we’ll see one of the above values, correlating the requesting application and the requested service.
When a user, let's say, wants to use their microphone in a program that hasn't requested access yet, Apple will display a prompt, asking the user if they want to “Allow” or “Not Allow” access. These prompts can look different depending on the service. We can dump the contents of the binary property list (plist) located at [.highlight]/System/Library/PrivateFrameworks/TCC.framework/Resources/Localizable.loctable[.highlight], and see some of Apple's prompts in the plist.
ٰܲԳٱ
In our case, this is the key/value pair that applies to our specific use case where [.highlight]%@[.highlight] is the client making the request.
Let's examine our root-level TCC database, located at [.highlight]/Library/Application Support/com.apple.TCC.db[.highlight], take a peek at an entry, and map the columns to the values. In this case, we're looking at the system extension from Red Canary's tool.
[.highlight]kTCCServiceEndpointSecurityClient - service (a system extension with the Endpoint Security entitlement)[.highlight]
[.highlight]com.redcanary.agent.securityextension - client (generally the Bundle Identifier (or path) of the client making the request)[.highlight]
[.highlight]0 - client_type (the client is a bundle ID(0) or an absolute path(1), which is common for debug tools or Xcode projects)[.highlight]
[.highlight]2 - auth_value (user action taken - denied(0), unknown(1), allowed(2), limited(3))[.highlight]
[.highlight]4 - auth_reason[.highlight] [.highlight](how the user took the action)[.highlight]
[.highlight]1 - auth_version[.highlight]
[.highlight]"X'212 bytes'" - csreq (binary blob)[.highlight]
[.highlight]NULL - policy_id[.highlight]
[.highlight]0 - indirect_object_identifier_type[.highlight]
[.highlight]UNUSED - indirect_object_identifier (bundle ID or absolute path of the client interaction)[.highlight]
[.highlight]NULL - indirect_object_code_identity[.highlight]
[.highlight]0 - flags[.highlight]
[.highlight]1681493977 - last_modified (last time it was modified in epoch time)[.highlight]
[.highlight]NULL - pid[.highlight]
[.highlight]NULL - pid_version[.highlight]
[.highlight]UNUSED - boot_uuid[.highlight]
[.highlight]0 - last_reminded[.highlight]
Understanding these different fields can help us navigate all what TCC is tracking.
MDM Overrides
One odd caveat of TCC is the MDMOverrides.plist located in the same com.apple.TCC directory. This binary property list contains MDM-specific TCC permissions. Via MDMs, administrators can deploy payloads, called PPPC payloads, that get added to the [.highlight]System Settings > Profiles[.highlight]. Here, admins can specify TCC permissions they want enabled or not. This is paramount in allowing admins to deploy software silently, run commands on the endpoint, and lots more.
However, because these permissions are added to the MDMOverrides.plist, as opposed to the TCC.db, they sometimes go unreflected in the UI. This can make triage of deployment issues tedious while attempting to cross reference files. In the meantime, most users cannot assist since the UI goes unchanged.
We've also seen issues where MDMs give some system binaries too broad of permissions. In one case, we observed an MDM giving bash full disk access (FDA) to its out-of-the-box, primary payload. Unfortunately, because they didn't only give their own signed agent permissions, then call bash from their agent, they gave (and actively give) bash carte blanche to the entire system. When I discovered this, I checked my TCC permissions in the UI, then I checked the actual sqlite database, via sqlite3 [.highlight]/Library/Application Support/com.apple.TCC/TCC.db[.highlight] before I realized that this was buried roughly halfway through my MDMOverrides file. Although I can understand Apple's design idea behind this—making it so MDMs can operate behind the scenes to add these permissions, if administrators are unaware of the effect of the payloads they're deployed, this could be an easy way for a threat actor to easily live-off-the-land.
Wrap Up
TCC is arguably one of the primary user-facing security features provided by Apple out of the box and is one of the first lines of defense to protect against on-disk abuse. Understanding its building blocks and operations can help security professionals and administrators, and even end users, navigate its labyrinth.
Next time, on Full Transparency, we’ll discuss the MDMOverrides property list and all of the nuances therein.
Sign Up for Blog Updates
Subscribe today and you’ll be the first to know when new content hits the blog.