Where in the World is Carmen Sandiego: Abusing Location Services on macOS

Introduction

Recently, I have been diving into understanding Transparency, Consent, and Control (TCC) on macOS. TCC is a control that limits an application’s ability to interact with various services on the operating system. It controls access to services such as camera, microphone, contacts, photos, folders on disc, location services, and more. If you want to know more about TCC, I highly recommend you read this blogpost by Keith Johnson.

While looking for bugs in TCC, I needed to write a proof-of-concept (POC) application that attempted to access the user’s location. This blogpost details what I learned about Location Services, how it works, the journey that took me there, and a tool release.

Transparency, Consent, and Control (TCC)

TCC (Transparency, Consent, and Control) is a mechanism in macOS to limit and control application access to certain features, usually from a privacy perspective. This can include things such as location services, contacts, photos, microphone, camera, accessibility, full disk access, and a bunch more. TCC was introduced with OSX Mavericks and has gone through a number of changes since to expand what it has control over. TCC also appears to exist and provide the same functionality on iOS …
- Keith Johnson (source)

Security & Privacy UI

Below, you’ll see the left column shows TCC-protected services and the right column shows the associated applications that are allowed to interact with that particular service.

Security & Privacy UI

TCC Prompts

Zoom Application Requesting Camera Access

tccutil

### Reset all permissions for a single TCC-protected service.
### All applications previously granted Microphone access will be
### revoked
$ sudo tccutil reset Microphone### Reset all permissions for a single application identified by
### bundle ID. All permissions previously granted to Safari will be
### revoked
$ sudo tccutil reset com.apple.Safari ### Reset all permissions for all TCC-protected services. All
### applications granted access to any TCC-protected service will be
### revoked
$ sudo tccutil reset All

What’s Happening Under the Hood?

Information about what applications can access what services is all stored within two SQLite databases:

  • /Library/Application Support/com.apple.TCC/TCC.db
  • ~/Library/Application Support/com.apple.TCC/TCC.db

The first path is a system-wide database and the second path is a per-user database. These databases are protected by System Integrity Protection (SIP), but they can be read if you grant Full Disk Access permissions to your application.

Introducing SwiftParseTCC

To further my understanding of TCC, I wrote a TCC database parser based on Keith Johnson’s blogpost called SwiftParseTCC. My tool provides some additional context on the data returned from TCC.db that may not be as apparent when using only a SQLite client.

SwiftParseTCC Help Output
SwiftParseTCC Text Table Output

If you use SwiftParseTCC (or any SQLite database client) on TCC.db, you’ll see some familiar fields from the Security & Privacy UI.

  • service — The internal name used for various TCC-protected services
  • client — The application that requested access to a particular service
  • client_type — Whether the application is identified by bundle ID or absolute path
  • auth_value — Whether the application is allowed to access the TCC-protected service

Now we know when a user allows/denies a TCC prompt, their choice adds an entry to TCC.db. Additionally, we also now understand that tccutil simply removes entries from TCC.db.

Enough talk about TCC, I thought this blogpost was about Location Services?

Is Location Services TCC-Protected?

kTCCServiceLiverpool within SwiftParseTCC Output

Reading through Keith’s blogpost, the service appears to be related to Location Services, but may not apply to macOS.

kTCCServiceLiverpool Description From Keith’s Blogpost

So it seems that Safari, Notes, and TrustedPeersHelper should have access to Location Services. Let’s write a program that accesses Location Services to obtain GPS coordinates and see if our application shows up in TCC.db.

Introducing SwiftLiverpool

SwiftLiverpool Output

SwiftLiverpool is a Swift CLI tool that leverages the CoreLocation API to interact with Location Services and extract latitude, longitude, altitude, and more.

If our assumption about kTCCServiceLiverpool are correct, when SwiftLiverpool is run, a TCC prompt will ask if the user wants to allow access to Location Services and an entry will be added to TCC.db. Let’s start with a clean slate by resetting TCC permissions with sudo tccutil reset All.

Note: In the image below, SwiftLiverpool was previously given access to Location Services through a pop-up.

Location Services Not Reset

Interesting … even after resetting TCC permissions, applications previously granted Location Services permissions were not reset. Let’s try running our application and inspecting the TCC database.

SwiftLiverpool Does Not Appear Within TCC.db

It seems that our application is able to interact with Location Services while not having an entry within either the system or user-specific TCC database. Location Services does not appear to be protected by TCC, so what actually protects/controls it?

Location Services (locationd)

Gist Comment

Plist files are a form of configuration files and can be formatted as XML, JSON or binary. Let’s take a look at /var/db/locationd/clients.plist using plutil (you must be sudo or root):

slyd0g@Justins-MBP~$ plutil -p /var/db/locationd/clients.plist
/var/db/locationd/clients.plist: file does not exist or is not readable or is not a regular file (Error Domain=NSCocoaErrorDomain Code=257 "The file “clients.plist” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/db/locationd/clients.plist, NSUnderlyingError=0x7f8fb4506e90 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}})
slyd0g@Justins-MBP~$ sudo plutil -p /var/db/locationd/clients.plist
{
"com.apple.locationd.executable-/Users/slyd0g/Projects/SwiftLiverpool/build/Debug/SwiftLiverpool" => {
"Authorized" => 1
"BundleId" => "com.apple.locationd.executable-/Users/slyd0g/Projects/SwiftLiverpool/build/Debug/SwiftLiverpool"
"Executable" => "/Users/slyd0g/Projects/SwiftLiverpool/build/Debug/SwiftLiverpool"
"LocationTimeStopped" => 660004429.982445
"ReceivingLocationInformationTimeStopped" => 660004431.985412
"Registered" => "/Users/slyd0g/Projects/SwiftLiverpool/build/Debug/SwiftLiverpool"
"Requirement" => "cdhash H"c670128640c6e2a8f7c33cda58d91d14c7062f2b""
"Whitelisted" => 0
}
"com.google.Chrome" => {
"Authorized" => 0
"BundleId" => "com.google.Chrome"
"BundlePath" => "/Applications/Google Chrome.app"
"Registered" => ""
"Requirement" => "(identifier "com.google.Chrome" or identifier "com.google.Chrome.beta" or identifier "com.google.Chrome.dev" or identifier "com.google.Chrome.canary") and certificate leaf = H"c9a99324ca3fcb23dbcc36bd5fd4f9753305130a""
"Whitelisted" => 0
}
"com.microsoft.VSCode" => {
"Authorized" => 1
"BundleId" => "com.microsoft.VSCode"
"BundlePath" => "/Applications/Visual Studio Code.app"
"Registered" => ""
"Requirement" => "identifier "com.microsoft.VSCode" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = UBF8T346G9"
"Whitelisted" => 0
}
}

Ah-ha! These applications match what is reflected within the Security & Privacy UI under Location Services. So locationd consumes /var/db/locationd/clients.plist, which is a binary plist that defines the “clients” that can access Location Services.

I wanted to see if I could remove the file, to reset Location Services, or write to the file and grant arbitrary applications access to location.

sh-3.2# rm /var/db/locationd/clients.plist
override rw-r--r-- _locationd/_locationd for /var/db/locationd/clients.plist? y
rm: /var/db/locationd/clients.plist: Operation not permitted

(Un)fortunately, I couldn’t delete clients.plist even from a privileged context. I then granted iTerm2 “Full Disk Access” permissions within TCC and tried again.

slyd0g@Justins-MBP~$ rm /var/db/locationd/clients.plist
rm: /var/db/locationd/clients.plist: Permission denied
slyd0g@Justins-MBP~$ sudo rm /var/db/locationd/clients.plist
Password:
slyd0g@Justins-MBP~$ sudo ls /var/db/locationd/
Library

With “Full Disk Access” and root permissions, I was able to delete clients.plist. You can also swap clients.plist with your own malicious.plist and grant any application access to Location Services. I’ll leave this as an exercise to the reader ;)

Copying a Malicious Plist File

Remember how we couldn’t reset Location Services earlier with tccutil?We can now reset Location Services within the Security & Privacy UI by deleting the clients.plist file and restarting locationd.

Resetting Location Services within Security & Privacy UI

Conclusion

Location Services is configured using a binary plist file, /var/db/locationd/clients.plist, that is consumed by a daemon, locationd. With root permissions and “Full Disk Access”, a malicious user can overwrite the clients.plist file with a malicious copy to allow arbitrary applications access to Location Services.

Thanks for taking the time to read this post, I hope you learned a little about macOS, TCC, and Location Services!

References

https://gist.github.com/haircut/aeb22c853b0ae4b483a76320ccc8c8e9

--

--

I break computers and skateboards and write about the former

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store