Blog Archives

accessing TCC.db without privileges



Earlier this year, Digita Security’s Patrick Wardle took apart a cross-platform backdoor trojan he nicknamed ”ColdRoot’. Wardle was retro-hunting possible malware by searching for apps on VirusTotal that access Apple’s TCC privacy database.

For those unfamiliar, TCC.db is the database that backs the System Preferences > Security & Privacy | Accessibility preferences pane and which controls, among other things, whether applications are allowed access to the Mac’s Accessibility features. Of interest from a security angle is that one of the permissions an app with access to Accessibility can gain is the ability to simulate user clicks, such as clicking “OK” and similar buttons in authorisation dialogs.

One particular comment in Wardle’s article caught my eye:

there is no legitimate or benign reason why non-Apple code should ever reference [the TCC.db] file!

While in general that is probably true, there is at least one good reason I can think of why a legitimate app might reference that file: reading the TCC.db used to be the easiest way to programmatically retrieve the list of apps that are allowed Accessibility privileges, and one reason why a piece of software might well want to do that is if it’s a piece of security software like DetectX Swift.

If your aim is to inform unsuspecting users of any changes or oddities in the list (such as adware, malware or just sneaky apps that want to backdoor you for their own ends), then reading TCC.db directly is the best way to get that information.


Just call me ‘root’

Since Apple put TCC.db under SIP protection subsequent to my reports on Dropbox’s user-unfriendly behaviour, apps are no longer able to write to the database via SQL injection. An app with elevated privileges can, however, still read the database. A sufficiently privileged app (or user) can output the current list with:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db 'select * from access'

On my machine, this indicates that there are twelve applications in the System Preferences’ Privacy pane, all of which are enabled save for two, namely LaunchBar and Safari:



We can see from the output that LaunchBar and Safari both have the ‘allowed’ integer set to ‘0’ (the middle of the three values in “0|0|1”) , whereas all the other apps have it set to ‘1’ (“0|1|1”).

It’s not clear to me why reading the database should require privileges. Certainly, Apple have provided APIs by which developers can test to see if their own apps are included in the database or not. The AXIsProcessTrusted() global function, for example, will return whether a calling process is a trusted accessibility client (see AXUIElement.h for related functions):

However, there remains a case (as I will demonstrate shortly) where developers may well need to know whether apps other than their own are, or are not, in the list. Moreover, there doesn’t seem to be any obvious vulnerability in allowing read access to that data, just so long as the write protection remains, as it does, in place.

The use case for being able to read the TCC.db database is clearly demonstrated by apps like DetectX Swift: security apps that conform to the principle of least privilege, always a good maxim to follow whenever practical. Asking users to grant elevated privileges just to check which apps are in Accessibility is akin to opening the bank vault in order to do an employee head count. Surely, it would be more secure to be able to determine who, if anyone, is in the vault without having to actually take the risk of unlocking the door.

Did they put a CCTV in there?

Without direct access to TCC.db, we might wonder whether there are any other less obvious ways by which we can determine which apps are able to access Accessibility features. There are three possibilities for keeping an eye on bad actors trying to exploit Accessibility without acquiring elevated privileges ourselves, each of which has some drawbacks.


1. Authorisation dialogs
The first is that we can read the property list that records all invocations of the Accessibility authorisation dialog, without admin rights:

defaults read ~/Library/Preferences/com.apple.universalaccessAuthWarning.plist

That gives us a list of all the apps that macOS has ever thrown the ‘some.app would like permission to control your computer’ dialog alert for, along with an indication of the user’s response (1= they opened sys prefs, 0= they hit Deny).



This list could prove useful for identifying adware installers that try to trick users into allowing them into Accessibility (looking at you, PDFPronto and friends), but it’s main drawback is that the list is historical and doesn’t indicate the current denizens of Accessibility. It doesn’t tell us whether the apps in the list are currently approved or not, only that each app listed once presented the user with the option of opening System Preferences and what the user chose to do about it at that time.



2. Distributed Notifications
The second option is that developers can register their apps to receive notifications when any other application gets added or removed from the list with code similar to this:

DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.accessibilityChanged), name: NSNotification.Name.init("com.apple.accessibility.api"), object: nil)

This ability was in fact added to DetectX Swift in version 1.04.



However, Apple hasn’t made this API particularly useful. Although we don’t need elevated privileges to call it, the NSNotification returned doesn’t contain a userInfo dictionary – the part in Apple’s notification class that provides specific information about a notification event. All that the notification provides is news that some change occurred, but whether that was an addition or a deletion, and which app it refers to, is not revealed:




Even so, notification of the change is at least something we can present to the user. Alas, this is only useful if the app that’s receiving the notification is actually running at the time the change occurs. For an on-demand search tool like DetectX Swift, which is only active when the user launches it, the notification is quite likely to be missed.

It would be nice, at least, if Apple would provide a more useful notification or an API for developers wishing to keep their users safe and informed. The lack of a userInfo dictionary in the notification was apparently reported as a bug to Apple several years back, but I suppose it could always use a dupe.



3. AppleScript – everyone’s favourite ‘Swiss Army Knife’
There is, as it turns out, a third way to reliably get exactly all the info we need about who has access to Accessibility. We can use AppleScript to return a complete list of apps in Accessibility that are enabled. Note that the output of this unprivileged script, shown here in the results pane of Script Debugger, returns a more readable version of the same list of apps we obtained from the privileged sqlite3 query of TCC.db, minus Safari and LaunchBar, which as we previously noted were not enabled:





Fantastic! There’s just one problem. While this AppleScript does not require blanket elevated privileges to run – in short, it doesn’t require an administrator password – it does need to be run by an app that is itself already in the list of Accessibility apps. If you have a script runner like Apple’s Script Editor, or third-party tools like Script Debugger or FastScripts, already approved in Accessibility, then you can run it without authorisation. It’s also worth noting that the script relies on launching and quitting System Preferences, which it attempts to do as quietly as possible.

As for DetectX Swift, I may consider adding something like this to a future version as an option for users who are happy to add DetectX to the list of apps in Accessibility.

Enjoy! 🙂



Have your own tips about accessing TCC.db? Let us know in the Comments!
Featured pic: Can’t STOP Me by smilejustbcuz

discovering how Dropbox hacks your mac

Screen Shot 2016-08-26 at 23.05.27

Update: Dropbox hack blocked by Apple in Sierra

Following my post revealing Dropbox’s Dirty Little Security Hack a few weeks ago, I thought I’d look deeper into how Dropbox was getting around Apple’s security.

After a little digging around in Apple’s vast documentation, it occurred to me to check the authorization database and see if that had been tampered with. According to the docs:

In a policy-based system, a user requests authorization—the act of granting a right or privilege—to perform a privileged operation. Authorization is performed through an agent so the user doesn’t have to trust the application with a password. The agent is the user interface— operating on behalf of the Security Server—used to obtain the user’s password or other form of identification, which also ensures consistency between applications. The Security Server—a Core Services daemon in OS X that deals with authorization and authentication—determines whether no one, everyone, or only certain users may perform a privileged operation.

The list of authorization “rights” used by the system to manage this “policy based system” is held in /var/db/auth.db database, and a backup or default copy is retained in /System/Library/Security/authorization.plist.

Looking at the default with

defaults read /System/Library/Security/authorization.plist

we can find that there is an authorization right for System Preferences’ Accessibility list, which says:

"system.preferences.accessibility" = {
class = user;
comment = "Checked when making changes to the Accessibility Preferences.";
group = admin;
shared = 0;
timeout = 0;

That file’s comments also state that “The allow-root property specifies whether a right should be allowed automatically if the requesting process is running with uid == 0. This defaults to false if not specified.”

In other words, if allow-root isn’t explicitly set, the default is that even a process with root user privileges does not have the right to perform that operation. Since that’s not specified in the default shown above, then even root couldn’t add Dropbox to the list of apps in Accessibility preferences. Is it possible then, that Dropbox had overriden this setting in the auth.db? Let’s go and check!

To see what the current policies are, you have to actually read the sql database in /var/db/auth.db. There’s various ways of doing that, but the easiest for me was to access auth.db through the command line using the security tool. Issuing the following command in Terminal will return us the currently active policy for Accessibility:

security authorization read system.preferences.accessibility

On my machine, this returned:

Screen Shot 2016-08-26 at 20.57.12

Root wasn’t allowed to override Accessibility, and authenticate was on, so it couldn’t be this way that Dropbox was hacking my mac.

Security on OS X is a complex beast, however, and there are other authorization protocols at work. One that I already knew of is tccutil. If you issue man tccutil in Terminal, you’ll see this:

tccutil(1) BSD General Commands Manual tccutil(1)

NAME
tccutil — manage the privacy database

SYNOPSIS
tccutil command service

DESCRIPTION
The tccutil command manages the privacy database, which stores decisions the user has made about
whether apps may access personal data.

One command is current supported:

reset Reset all decisions for the specified service, causing apps to prompt again the next time
they access the service.

EXAMPLES
To reset all decisions about whether apps may access the address book:

tccutil reset AddressBook

Darwin April 3, 2012 Darwin
(END)

I had heard of a hack of this utility that was related directly to adding apps to Accessibility list over a year ago when I stumbled across this stackexchange page. In short, what that hack suggests is that you modify tcc directly by inserting an entry into the sql database located here /Library/Application Support/com.apple.TCC/TCC.db.

You can read the current list with the command:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db 'select * from access'.

To insert an app in the list, you grab it’s bundle identifier (in the case of Dropbox, that’s com.getdropbox.dropbox), and issue:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db “REPLACE INTO access VALUES(‘kTCCServiceAccessibility’,’com.getdropbox.dropbox’,0,1,1,NULL, NULL);”

(*note the code given on the stackexchange page isn’t quite correct for the latest builds of the mac operating system, in which the access table now has 7 columns and so requires and extra “NULL” on the end as shown above).

I tested this with several of my own apps and found it worked reliably. It’ll even work while System Preferences is open, which is exactly the behaviour I saw with Dropbox.

It remained to prove, though, that this was indeed the hack that Dropbox was using, and so I started to look at what exactly Dropbox did after being given an admin password on installation or launch. Using DetectX, I was able to see that Dropbox added a new folder to my /Library folder after the password was entered:

Screen Shot 2016-08-26 at 21.36.35
Screen Shot 2016-08-26 at 21.37.09

As can be seen, instead of adding something to the PrivilegedHelperTools folder as is standard behaviour for apps on the mac that need elevated privileges for one or two specialist operations, Dropbox installs its own folder containing these interesting items:

Screen Shot 2016-08-26 at 21.40.45

Not one, but three binaries! I wonder what they do? The first thing I did on each was to run the strings command on them. I still haven’t determined what that 1.5MB DropboxHelperInstaller binary is doing (that’s pretty big for a binary for a helper app), but its jam-packed with strings relating to file compression and encryption. The string output for dbfseventsd binary didn’t reveal anything much interesting, but with the deliciously named dbaccessperm file, we finally hit gold and the exact proof I was looking for that Dropbox was using a sql attack on the tcc database to circumvent Apple’s authorization policy:

Screen Shot 2016-08-26 at 23.05.27

This is all the more telling when we look at what Dropbox themselves say when queried about why their app is in the list of Accessibility apps here. After a great deal of obfuscation, misdirection and irrelevance in which they mention everything about permissions in general and nothing about Accessibility in particular, or that they’re hacking their way into the user’s Accessibility list rather than going through the supported channel of presenting the user with a dialog box and asking for permission, comes this line:

we need to request all the permissions we need or even may need in the future.
(my emphasis)

Ostensibly, that’s in the context of Drobpox on mobile apps, but since the question isn’t related to mobile apps at all, I think interpreting anything said there as being honest is naive at best. What I do suspect, especially in light of the fact that there just doesn’t seem to be any need for Dropbox to have Accessibility permissions, is that it’s in there just in case they want that access in the future. If that’s right, it suggests that Dropbox simply want to have access to anything and everything on your mac, whether it’s needed or not.

The upshot for me was that I learned a few things about how security and authorisation work on the mac that I didn’t know before investigating what Dropbox was up to. But most of all, I learned that I don’t trust Dropbox at all. Unnecessary privileges and backdooring are what I call untrustworthy behaviour and a clear breach of user trust. With Apple’s recent stance against the FBI and their commitment to privacy in general, I feel moving over to iCloud and dropping Dropbox is a far more sensible way to go for me. For those of you who are stuck with Dropbox but don’t want to allow it access to Accessibility features, you can thwart Dropbox’s hack by following my procedure here.

🙂

Further Reading:

Dropbox hack blocked by Apple in Sierra

Revealing Dropbox’s Dirty Little Security Hack

Hackers steal over 60m Dropbox user account passwords

How keyloggers get around OSX Security

%d bloggers like this: