Tuesday, July 13, 2021

Bypassing TCC By Changing the Environment

Matt Shockley (tweet, Medium):

TCC stores these user-level entitlements in a SQLite3 database on disk at $HOME/Library/Application Support/com.apple.TCC/TCC.db. Apple uses a dedicated daemon, tccd, for each logged-in user (and one system level daemon) to handle TCC requests. These daemons sit idle until they receive an access request from the OS for an application attempting to access protected data


Obviously being able to write directly to the database completely defeats the purpose of TCC, so Apple protects this database itself with TCC and System Integrity Protection (SIP). Even a program running as root cannot modify this database unless it has the com.apple.private.tcc.manager and com.apple.rootless.storage.TCC entitlements. However, the database is still technically owned and readable/writeable by the currently running user, so as long as we can find a program with those entitlements, we can control the database.


Essentially, when the TCC daemon attempts to open the database, the program tries to directly open (or create if not already existing) the SQLite3 database at $HOME/Library/Application Support/com.apple.TCC/TCC.db. While this seems inconspicuous at first, it becomes more interesting when you realize that you can control the location that the TCC daemon reads and writes to if you can control what the $HOME environment variable contains. […] Thus, I could set the $HOME environment variable in launchctl to point to a directory I control, restart the TCC daemon, and then directly modify the TCC database to give myself every TCC entitlement available without ever prompting the end user.

So SIP is still protecting the normal path, but the system relies on tccd, which has been redirected to a different path. Apple fixed this 4.5 months later, in July 2020.

Patrick Wardle:

TCC continues to be a massive pain in the butt for legitimate software/app developers.

...but for hackers? Yah, not so much at all 😭😭😭😭😭

For example (as a legitimate soft dev), how can my updater tell if my app was already granted certain TCC privileges (so I don’t have to re-prompt the user)?

And why do I have to manually restart TCCd to avoid a myriad of (broken) caching issues?


2 Comments RSS · Twitter

I would say that roughly 50% of my user support requests are related to Apple’s broken permission system - 50%. For Keyboard Maestro, a complex tool with complex UI, and the most common question I get boils down to simply "how can I get Accessibility permissions working?". This permission system has been broken in a variety of ways since Mojave and it boggles the mind that it can remain so broken, and so inconsistent. Bugs like requiring the user to toggle Accessibility permissions off and then on again, not being able to toggle the permission checkboxes at all, inconsistency as to whether Keyboard Maestro.app itself needs the permission, or the contained Keyboard Maestro Engine.app or both, bugs where the settings don't stick, or don't show, or say they are on but aren't, or reset every launch.

It's unbelievable to imagine that the security system can be secure when the permission system is so buggy.

@Peter My sympathies. I’ve been running into most of those issues with my apps, too.

Leave a Comment