The rootless-init tool allows reloading of rootless.conf rules without presence of filesystem trigger

Originator:bruienne
Number:rdar://33382713 Date Originated:18-Jul-2017 03:33 PM
Status:Open Resolved:
Product:macOS + SDK Product Version:10.12.5
Classification:Security Reproducible:Always
 
Summary:
The rootless-init tool that ships with SIP-protected versions up to and including macOS 10.12 runs as a daemon from /System/Library/LaunchDaemons/com.apple.rootless.init.plist which watches for the presence of /System/Library/Sandbox/Compatibility.bundle/Contents/Resources/paths with the purpose of updating rootless rules when the filesystem trigger is created by entitled Apple tools. A user (regular or root) should not have the ability to force reloading the ruleset. We have determined that when running `/usr/libexec/rootless-init -b` after modifying /System/Library/Sandbox/rootless.conf (more on this in a moment) instead of performing a NOP, rootless-init will actually reapply the rules in /System/Library/Sandbox/rootless.conf and change SIP protection based on any changes it finds like removed entries, modified exceptions or new additions.

In order to modify /System/Library/Sandbox/rootless.conf it is necessary to boot into Recovery mode or NetInstall, make the change and reboot into normal macOS. One can then run `sudo /usr/libexec/rootless-init -b` and have the changes applied. In addition during our testing we noticed that it is also possible to replace /System/Library/Sandbox/rootless.conf with a symlink to a non-SIP protected location on the filesystem, again while SIP is disabled. After rebooting to normal SIP-protected mode the OS does not appear to stat /System/Library/Sandbox/rootless.conf to determine whether it is an actual file or something else. Because of this one can gain (with a one-time setup in Recovery or NetInstall) on-the-fly SIP filesystem protection modification by:

- Making changes to the target of the /System/Library/Sandbox/rootless.conf symlink, which SIP does not block
- Running `sudo /usr/libexec/rootless-init -b` to have those changes take effect

While not a SIP bypass in a strict sense it does allow those meaning to bypass SIP protection on some or all of the filesystem while not changing the overall SIP status to do so. It appears that rootless-init should perform stricter file stat and option flag checking in order to prevent arbitrary reloading of SIP filesystem protection rules.

Steps to Reproduce:
1. Boot into Recovery or NetInstall
2. Launch Terminal.app
3a. Make changes to /System/Library/Sandbox/rootless.conf by removing an entry, creating an exception, etc
or
3b. Copy /System/Library/Sandbox/rootless.conf to a non-SIP protected filesystem location, create a symlink to it at /System/Library/Sandbox/rootless.conf and make some changes
4. Reboot into normal SIP-protected mode
5. Launch Terminal.app
6. Run `sudo /usr/libexec/rootless-init -b`
7. Instead of no output "repairing filesystem" will be seen
8. Paths that were modified or removed from rootless.conf will be mutable whereas previously they were not

Additionally, if 3b was performed:
9. Make changes to the symlink target of /System/Library/Sandbox/rootless.conf
10. Run `sudo /usr/libexec/rootless-init -b` again
11. Changes are picked up an applied to the filesystem

Expected Results:
Expected behavior is for rootless-init to never reload rootless.conf entries when run by a user. Only entitled Apple tools should have this ability.

Actual Results:
A privileged user is able to force reloading rootless.conf and change filesystem protection status on files and folders.

Version:
10.12.5

Notes:
This issue was found by Michael Lynn of Facebook and Pepijn Bruienne of Duo Security.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!