System Integrity Protection – Adding another layer to Apple’s security model
As part of the release of OS X El Capitan, Apple has added a new layer named System Integrity Protection (SIP) to its security model. To understand how System Integrity Protection fits in, let’s first take a look at Apple’s security model as it existed as of OS X Yosemite.
Gatekeeper is one of the outer lines of defense. It allows users to restrict which sources they can install applications from, with the general idea being that malware will not be from an allowed source.
OS X also uses sandboxing extensively. A sandbox typically provides a tightly controlled set of resources for programs to run in. Network access, the ability to inspect the host system, or reading from input devices is usually disallowed or heavily restricted.
OS X uses the Unix permissions model as defined by POSIX, which governs which users and groups can access which files and directories. If a particular user account requests access to a particular file or directory and does not have the necessary rights, that account is refused access.
The innermost layer of defense are keychains. Keychains are very specialized databases which are designed for the storing of secrets, like passwords, private keys, PIN numbers, and then controlling access to those secrets. To help protect these secrets, keychains are encrypted.
There’s an issue with this model though and it’s been there for decades. It pre-exists OS X and even pre-exists Apple as a company. That issue is found in the POSIX permissions layer.
Root
Root is the superuser for a Unix system and the Unix permissions model is designed around the assumption that root has access to everything. Apple has not ignored this issue and has put some controls in place to limit the actual root user. These controls include disabling the root user account, discouraging its use, and providing ways to access elevated or root privileges using other means.
However, the root user account is still present and still can do anything on the system.
System Integrity Protection
To limit what the superuser can do and add another layer to OS X’s security model, Apple has developed SIP and deployed it as part of OS X El Capitan. SIP is designed to limit the power of root and to protect the system even from the superuser. For more details, see below the jump.
SIP is an overall security policy with the goal of preventing system files and processes from being modified by third parties. To achieve this, it has the following concepts:
- File system protection
- Runtime protection
- Kernel extension protection
File system protection
SIP prevents parties other than Apple from adding, deleting or modifying directories and files stored in certain directories:
- /bin
- /sbin
- /usr
- /System
Apple has indicated that the following directories are available for developers to access:
- /usr/local
- /Applications
- /Library
- ~/Library
All directories in /usr except for /usr/local are protected by SIP.
It is possible to add, remove or change SIP-protected files and directories via an installer package which is signed by Apple’s own certificate authority. This allows Apple to make changes to SIP-protected parts of the OS without needing to change the existing SIP protections.
The certificate authority in question is reserved by Apple for their own use; Developer ID-signed installer packages are not able to alter SIP-protected files or directories.
To define which directories are protected, Apple has currently defined two configuration files on the filesystem. The primary one is found at the location below:
/System/Library/Sandbox/rootless.conf
The rootless.conf file lists all the applications and the top-level of directories which SIP is protecting.
Applications
SIP is protecting the core apps which OS X installs into /Applications and /Applications/Utilities.
This means it will no longer be possible to delete the applications which OS X installs, even from the command line when using root privileges.
Directories
SIP is also protecting a number of directories and symlinks outside of /Applications and the top level of those directories are also listed in the rootless.conf file. In addition to protections, Apple has also defined some exceptions to SIP’s protection in the rootless.conf file, and those exceptions are marked with asterixes. These exemptions from SIP’s protection mean that it is possible to add, remove or change files and directories within those locations.
Among those exceptions are the following:
/System/Library/User Template – where OS X stores the template directories it uses when creating home folders for new accounts.
/usr/libexec/cups – where OS X stores printer configuration information
When I’ve spoken with Apple engineers about how this configuration file was updated and if third parties could add their own exceptions to it, it was made clear that Apple considers this file theirs and that any third parties’ changes to it would be overwritten by Apple.
To see which files have been protected by SIP, use the ls command with the capital O flag in Terminal:
ls -O
SIP-protected files will be labeled as restricted.
One important think to know is that even if a symlink is protected by SIP, that does not necessarily mean that the directory they’re linking to is being protected by SIP. At the root level of an OS X El Capitan boot drive, there are several SIP-protected symlinks pointing to directories stored inside the root-level directory named private.
However, when the contents of the directory named private are examined, the directories which those symlinks point to are not protected by SIP and both they and their contents can be moved, edited or changed by processes using root privileges.
In addition to the list of SIP exceptions which Apple has set in rootless.conf, there is a second list of SIP exceptions. This list includes a number of directories and application names for third-party products. Similar to rootless.conf, this exclusion list is Apple’s and any third parties’ changes to it will be overwritten by Apple.
/System/Library/Sandbox/Compatibility.bundle/Contents/Resources/paths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/System/Library/CFMSupport | |
/System/Library/CoreServices/Applications/Directory Utility.app/Contents/PlugIns/ADmitMac.daplug | |
/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/iLifeSlideshowTypes.bundle | |
/System/Library/CoreServices/SecurityAgentPlugins/CentrifyPAM.bundle | |
/System/Library/CoreServices/SecurityAgentPlugins/CentrifySmartCard.bundle | |
/System/Library/CyborgRAT.kext | |
/System/Library/Extensions/IONetworkingFamily.kext/Contents/PlugIns/AppleRTL815XComposite109.kext | |
/System/Library/Extensions/IONetworkingFamily.kext/Contents/PlugIns/AppleRTL815XEthernet109.kext | |
/System/Library/Filesystems/DAVE | |
/System/Library/Filesystems/fusefs_txantfs.fs | |
/System/Library/Filesystems/ufsd_NTFS.fs | |
/System/Library/Fonts/encodings.dir | |
/System/Library/Fonts/fonts.dir | |
/System/Library/Fonts/fonts.list | |
/System/Library/Fonts/fonts.scale | |
/System/Library/HuaweiDataCardDriver.kext | |
/System/Library/LaunchAgents/com.paragon.NTFS.notify.plist | |
/System/Library/LaunchDaemons/com.absolute.rpcnet.plist | |
/System/Library/LaunchDaemons/com.intel.haxm.plist | |
/System/Library/LaunchDaemons/com.seagate.TBDecorator.plist | |
/System/Library/LaunchDaemons/de.novamedia.nmnetmgrd.plist | |
/System/Library/PrivateFrameworks/BrowserKit.framework | |
/System/Library/PrivateFrameworks/Helium.framework | |
/System/Library/PrivateFrameworks/LiveType.framework | |
/System/Library/PrivateFrameworks/ProKit.framework | |
/System/Library/PrivateFrameworks/iLifeSlideshow.framework | |
/System/Library/QuickTime/QuickTimeMPEG2.component | |
/System/Library/QuickTime/WiretapDataHandler.component | |
/System/Library/Services/KAVService.service | |
/System/Library/Services/Send to Kindle.workflow | |
/System/Library/StartupItems | |
/System/Library/USBExpressCardCantWake_Huawei.kext | |
/sbin/amconfig | |
/sbin/fsck_ufsd_NTFS | |
/sbin/mount_cifs | |
/sbin/mount_fusefs_txantfs | |
/sbin/mount_ufsd_NTFS | |
/sbin/mount_vmhgfs | |
/sbin/newfs_fusefs_txantfs | |
/sbin/newfs_ufsd_NTFS | |
/sbin/rpctool | |
/usr/X11 | |
/usr/bin/FAHClient | |
/usr/bin/FAHCoreWrapper | |
/usr/bin/FAHViewer | |
/usr/bin/VBoxAutostart | |
/usr/bin/VBoxBalloonCtrl | |
/usr/bin/VBoxHeadless | |
/usr/bin/VBoxManage | |
/usr/bin/VBoxVRDP | |
/usr/bin/VirtualBox | |
/usr/bin/cups-calibrate | |
/usr/bin/escputil | |
/usr/bin/extlookup2hiera | |
/usr/bin/facter | |
/usr/bin/gnutar | |
/usr/bin/kashell | |
/usr/bin/kav | |
/usr/bin/nortonscanner | |
/usr/bin/nortonsettings | |
/usr/bin/nvconfigurator | |
/usr/bin/nvpmgr | |
/usr/bin/phidgetwebservice21 | |
/usr/bin/puppet | |
/usr/bin/shake | |
/usr/bin/stkLaunchAgent.sh | |
/usr/bin/testpattern | |
/usr/bin/vagrant | |
/usr/bin/vboxwebsrv | |
/usr/discreet | |
/usr/include/gutenprint | |
/usr/lib/cshost | |
/usr/lib/gutenprint | |
/usr/lib/libMatroxMpeg2IFrameCodec.dylib | |
/usr/lib/libUFSDNTFS.dylib | |
/usr/lib/libgutenprint.2.0.3.dylib | |
/usr/lib/libgutenprint.2.dylib | |
/usr/lib/libgutenprint.a | |
/usr/lib/libgutenprint.dylib | |
/usr/lib/libgutenprint.la | |
/usr/lib/libnv6.dylib | |
/usr/lib/libnv6audit.dylib | |
/usr/lib/libnv6cli.dylib | |
/usr/lib/libnv6clit.dylib | |
/usr/lib/libnv6foreignras.dylib | |
/usr/lib/libnv6foreignrast.dylib | |
/usr/lib/libnv6gui.dylib | |
/usr/lib/libnv6guit.dylib | |
/usr/lib/libnv6http.dylib | |
/usr/lib/libnv6jobs.dylib | |
/usr/lib/libnv6jobst.dylib | |
/usr/lib/libnv6json.dylib | |
/usr/lib/libnv6jsont.dylib | |
/usr/lib/libnv6ndmp.dylib | |
/usr/lib/libnv6plugin.dylib | |
/usr/lib/libnv6plugint.dylib | |
/usr/lib/libnv6reports.dylib | |
/usr/lib/libnv6reportst.dylib | |
/usr/lib/libnv6scsi.dylib | |
/usr/lib/libnv6stats.dylib | |
/usr/lib/libnv6statst.dylib | |
/usr/lib/libnv6t.dylib | |
/usr/lib/libnv6xctl.dylib | |
/usr/lib/libnv6xpm.dylib | |
/usr/lib/libphidget21.jnilib | |
/usr/lib/libwkextmac.dylib | |
/usr/lib/pam/pam_centrifydc.so | |
/usr/lib/pkgconfig/gutenprint.pc | |
/usr/libexec/aksusbd | |
/usr/libexec/com.matrox.vpg.Agent | |
/usr/libexec/com.matrox.vpg.MaxAgent | |
/usr/libexec/cups/backend/cifs | |
/usr/libexec/hasplmd | |
/usr/local | |
/usr/netvault | |
/usr/sbin/AELWriter | |
/usr/sbin/cups-genppd.5.2 | |
/usr/sbin/cups-genppdupdate | |
/usr/sbin/fsctl_ufsd | |
/usr/sbin/jamf | |
/usr/sbin/jamfAgent | |
/usr/sbin/m_agent | |
/usr/sbin/m_agent_upgrade | |
/usr/sbin/nipalsm | |
/usr/sbin/nmnetmgrd | |
/usr/sbin/nmnetmgrd_launchd | |
/usr/sbin/nmnetmgrd_launchd_MT | |
/usr/sbin/palModuleMgr.sh | |
/usr/sbin/proxyhelper | |
/usr/sbin/qmasterca | |
/usr/sbin/qmasterd | |
/usr/sbin/qmasterprefs | |
/usr/sbin/qmasterqd | |
/usr/sbin/rpc.net | |
/usr/sbin/rpcset | |
/usr/sbin/rpcstartup | |
/usr/sbin/setbufsize | |
/usr/share/centrifydc | |
/usr/share/cshost | |
/usr/share/cups/calibrate.ppm | |
/usr/share/cups/mime/pharos.convs | |
/usr/share/cups/usb | |
/usr/share/doc/facter | |
/usr/share/doc/puppet | |
/usr/share/gutenprint | |
/usr/share/locale/ca/gutenprint_ca.po | |
/usr/share/locale/cs/gutenprint_cs.po | |
/usr/share/locale/da/gutenprint_da.po | |
/usr/share/locale/de/gutenprint_de.po | |
/usr/share/locale/el/gutenprint_el.po | |
/usr/share/locale/en_GB/gutenprint_en_GB.po | |
/usr/share/locale/es/gutenprint_es.po | |
/usr/share/locale/fi/gutenprint_fi.po | |
/usr/share/locale/fr/gutenprint_fr.po | |
/usr/share/locale/gl/gutenprint_gl.po | |
/usr/share/locale/hu/gutenprint_hu.po | |
/usr/share/locale/it/gutenprint_it.po | |
/usr/share/locale/ja/gutenprint_ja.po | |
/usr/share/locale/nb/gutenprint_nb.po | |
/usr/share/locale/nl/gutenprint_nl.po | |
/usr/share/locale/pl/gutenprint_pl.po | |
/usr/share/locale/pt/gutenprint_pt.po | |
/usr/share/locale/ru/gutenprint_ru.po | |
/usr/share/locale/sk/gutenprint_sk.po | |
/usr/share/locale/sl/gutenprint_sl.po | |
/usr/share/locale/sv/gutenprint_sv.po | |
/usr/share/locale/tr/gutenprint_tr.po | |
/usr/share/locale/uk/gutenprint_uk.po | |
/usr/share/locale/vi/gutenprint_vi.po | |
/usr/share/locale/zh_CN/gutenprint_zh_CN.po | |
/usr/share/locale/zh_TW/gutenprint_zh_TW.po |
Runtime protection
SIP’s protections are not limited to protecting the system from filesystem changes. There are also system calls which are now restricted in their functionality.
- task_for_pid() / processor_set_tasks() fail with EPERM
- Mach special ports are reset on exec(2)
- dyld environment variables are ignored
- DTrace probes unavailable
However, SIP does not block inspection by the developer of their own applications while they’re being developed. Xcode’s tools will continue to allow apps to be inspected and debugged during the development process.
For more details on this, I recommend taking a look at Apple’s developer documentation for SIP.
Kernel extension protection
SIP blocks installation of unsigned kernel extensions. In order to install a kernel extension on OS X El Capitan with SIP enabled, a kernel extension must:
- Be signed with a Developer ID for Signing Kexts certificate
- Install into /Library/Extensions
If installing an unsigned kernel extension, SIP will need to be disabled first.
Managing SIP
To help ensure that third parties will not be able to disable these protections, SIP’s configuration is stored in NVRAM rather than in the file system itself and is only configurable if the Mac is booted into one of two environments:
- The OS X Installer environment
- The OS X Recovery environment
Note: The OS X Installer and OS X Recovery environments are in fact the same environment from OS X’s perspective, with the main difference being that the OS X Installer environment contains a copy of the installation files for OS X and the Recovery environment does not.
Because SIP’s configuration is stored in NVRAM, SIP’s protection settings will apply to the entire machine and will persist even if the OS is reinstalled.
SIP can be managed to the extent of turning it on, turning it off, adding and removing IP addresses into a NetBoot whitelist and reporting on whether SIP is enabled or disabled. All changes to SIP’s configuration also require a reboot before they take effect.
The tool used to manage SIP is /usr/bin/csrutil. csrutil is able to work with SIP because it has a unique application entitlement assigned to it by Apple. This entitlement is viewable using the codesign command shown below:
codesign -d --entitlements - /usr/bin/csrutil
When you run csrutil without any associated commands, it will pull up the help page.
When booted from Recovery, the command used to enable SIP is csrutil enable:
csrutil enable
When booted from Recovery, the command used to turn SIP off is csrutil disable:
csrutil disable
When booted from Recovery, the command used to reset SIP’s configuration is csrutil clear:
csrutil clear
When csrutil clear is run, SIP goes back to its factory-default settings. That means SIP is enabled if it was disabled previously and any custom configuration is cleared out.
SIP and NetBoot
One of the custom configuration options available in SIP is the ability to set a whitelist for approved NetBoot servers. This whitelist is needed because the bless command in El Capitan is restricted by SIP from writing to NVRAM. This affects bless‘s ability to set Macs to boot from NetBoot sets because it needs to write that information to NVRAM.
This whitelist defines by IP address which NetBoot servers are trusted in your environment. Once those IP addresses are part of the whitelist, the bless command can set a Mac to NetBoot from a NetBoot set on a trusted NetBoot server. For more information about whether or not you need to whitelist your NetBoot server(s), please see the link below:
https://derflounder.wordpress.com/2015/09/05/netbooting-and-system-integrity-protection/
To help folks who need to use bless to set a NetBoot set as a startup drive, the csrutil tool includes functionality to add NetBoot servers to the whitelist. While booted from Recovery, use csrutil netboot add followed by an IP address to set the IP as being that of a NetBoot server approved for use by the bless command:
csrutil netboot add ip.address.here
While booted from Recovery, you can also remove NetBoot servers from the whitelist. To do this, use csrutil netboot remove followed by the IP address that you want to remove from the whitelist.
csrutil netboot remove ip.address.here
To see which NetBoot servers have been added to the whitelist, run csrutil netboot list.
csrutil netboot list
Running csrutil outside Recovery
If you try to run the csrutil enable and csrutil disable commands while booted from a regular boot drive, you will receive a message that these commands need to be run from Recovery. The current SIP configuration will remain unchanged.
Likewise, if you try to run the csrutil netboot add and csrutil netboot remove commands while booted from a regular boot drive, you will receive the message that csrutil was unable to save the configuration and the status of the NetBoot whitelist will remain unchanged.
What can be run while booted from a regular boot drive is csrutil’s reporting functions. For example, to learn if SIP is enabled or disabled, run csrutil status.
csrutil status
This command can be run without root privileges and will tell you if SIP is on or off.
If SIP is off, you may receive a confusing message which indicates that SIP is enabled, followed by a list of individual SIP functions which are disabled. If all functions listed are showing as being disabled, SIP is actually completely disabled; it’s just confusingly worded.
I actually have a bug report on this message. For those who wish to dupe it, it is bug ID 22361698 and is cross-posted to Open Radar here:
https://openradar.appspot.com/radar?id=4932475130216448
Likewise, you can run csrutil netboot list and it will report on which IPs have been set as allowed NetBoot sources when using the bless command.
Other custom SIP configuration options
It is also possible to enable SIP protections and selectively disable aspects of it, by adding one or more flags to the csrutil enable command. All require being booted from Recovery in order to set them:
Enable SIP and allow installation of unsigned kernel extensions
csrutil enable --without kext
When this option is enabled, running csrutil status should produce output similar to this.
Enable SIP and disable filesystem protections
csrutil enable --without fs
When this option is enabled, running csrutil status should produce output similar to this.
Enable SIP and disable debugging restrictions
csrutil enable --without debug
When this option is enabled, running csrutil status should produce output similar to this.
Enable SIP and disable DTrace restrictions
csrutil enable --without dtrace
When this option is enabled, running csrutil status should produce output similar to this.
Enable SIP and disable restrictions on writing to NVRAM
csrutil enable --without nvram
When this option is enabled, running csrutil status should produce output similar to this.
Conclusion
SIP is a big change, but I think it should also be considered a work in progress. I’m expecting to see additional changes to SIP’s functionality in both El Capitan and future releases of OS X, as Apple sees how SIP works in the real world.
Rich, thanks again for another informative article! Lots of great info here!
Hi Rich,
first thanks for your article.
Apple talks at the end of this documentation about a special option for enterprise environments:
https://developer.apple.com/library/prerelease/mac/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html
“Note: For certain enterprise configurations that do not allow booting to Recovery OS, System Integrity Protection can be configured by other means.”
As far as I know, the option which worked in the first beta releases of 10.11 was:
sudo nvram boot-args=”rootless=0″; osascript -e ‘tell app “loginwindow” to «event aevtrrst»’
Might it be possible to use this also in the final release of 10.11 now, if we disable the restrictions to write to nvram?
csrutil enable –without nvram
Would be great to know. Or does Apple offer other options for the enterprise we don’t know yet?
Marcel,
I’ve written a post on what Apple’s referring to in that note in the documentation:
https://derflounder.wordpress.com/2015/10/05/configuring-system-integrity-protection-without-booting-to-recovery-hd/
Many thanks as always, great news.
Re: sudo nvram boot-args=”rootless=0″
Does this mean you can actually switch off SIP from an earlier version of OS X, for instance to prevent quarantining stuff from /Applications during an upgrade?
Rich – Please let me know if you’d like different attribution or verbiage to the link from http://apple.blogoverflow.com/2015/10/el-capitan-resources/
That looks great, thanks!
Great post. Thanks for the useful and complete explanation!
Any workarounds for your Firstboot script that modifies the loginwindow.plist ?
Thanks for a great article. Even after disabling SIP, certain things do not work. The DTruss man page still (El Capitan 10.11.3) lists the example ‘dtruss df -h’ but entering that as root gives:
dtrace: failed to execute df: dtrace cannot control executables signed with restricted entitlements
The workaround–at least for now–is that files in the /bin directory are restricted, not the df command itself. So, as root:
cp /bin/df /tmp
dtruss /tmp/df -h
works just fine.
Good thorough article.
I’d note that since the SIP protection setting is stored in NVRAM, that it can be changed from disabled to enabled by resetting the Mac’s PRAM/NVRAM, by rebooting or powering up the Mac, and then before the screen lights up, holding down Command-Option-P-R until you hear a startup chime after the initial powerup or startup chime. Normally, resetting NVRAM requires you to shut down the Mac, and then to hold down the key combo until you hear two startup chimes after the initial powerup chime, but I found (at least on several Macbooks) that all that’s required to re-enable SIP is to restart the Mac (no need to shut down), and then to hold down the key combo until you hear just one more chime.
I am not a sys admin. I am a musician with a little bit of un*x knowledge. in order to make my macbook pro system work the way I want, I moved the /Library/Audio folder to a second internal drive. I then symlinked /Library/Audio to it. This worked great under 10.10. Then I upgraded to 10.11 and now I am having problems with one software product that writes an audio driver into Plugins/HAL. They told me that the problem is because of “apple’s new security feature”. They won’t help me. Everything else on my system works find under 10.11.
Using SIP is there a way to turn off SIP for this path so the system can get at the driver? or…?
thanks for your help!
Thank you for this insightful post! Great explanation. The only thing I thought was missing is what “csrutil enable –no-internal” does?
The fastest way to disable System Integrity Protection is to restart and hold Command+r+s to boot into Single User Recovery Mode.
Is there a way to disable “Apple Internal”? I cannot seem to find a way. Even after doing ‘csrutil disable’ I am unable to mount the root folder in single user mode as writable. I believe it’s due to the Apple Internal configuration item.