There have been a bunch of discussions around SELinux Permissive mode recently in the Audio Mod & Kernel circles. I'd like to start a discussion here around the risks associated with Root and SELinux. I've done some research already (as of 5/15/2017) and will include my notes and conclusions below, but they may be subject to change as new information comes up.
The main question I wanted to answer is this:
Is being Rooted essentially the same as being in Permissive mode?
Background:
Security is always more secure in serialized layers; meaning that each layer has to be passed through one after the other. Unix provides its standard permissions as a single layer of security (for the security buffs out there this is a Discretionary Access Control system). SELinux adds an additional layer of security on top of the standard Unix Permissions by providing a Mandatory Access Control system through the enforcement of a global permissions policy. The main purpose of SELinux is to prevent escalation of privilege attacks, for example to prevent an MMS app from modifying Network Settings or accessing other resources not related to MMS. So SELinux essentially confines all apps (system or otherwise) to a realm of legitimate activity.
The SELinux Policy is actually a 'compiled' (more serialized than compiled, but it's referred to as compiled) version of a human-readable text version of the permissions contained in the policy. On a Stock Unrooted device the SELinux Policy is distributed with the ROM and is never modified except for during ROM upgrades if necessary. This provides the highest level of security (assuming the ROM provides a tight policy) since the SELinux Policy should only contain permissions for legitimate activities according to the device manufacturer and/or carrier. So SELinux would, in theory, restrict any malicious app to safe activities, preventing serious harm to your device & data.
Since the SELinux Policy restricts full access to the device in order to achieve root some of those restrictions need to be bypassed. How this is performed varies, but the end goal is the same : inject new permissions into the SELinux Policy to allow the root implementation full access to the device. If the root implementation is ethical then it should only inject permissions related to providing root access. Since root apps will likely require permissions not included in a device's Stock SELinux Policy most root implementations provide tools for injecting permissions into the SELinux Policy at runtime (selinux-inject, supolicy & magiskpolicy). Most root implementations also provide locations for startup scripts which are executed in a root context. These tools and scripts are used legitimately by the root implementation to maintain root access and by root apps to maintain stable functionality.
SELinux provides three modes : Enforcing, Permissive & Disabled (not covered in this discussion). In Enforcing mode SELinux will deny and log any requests for permissions against the SELinux Policy. Enforcing mode is meant for production devices (or devices for end users). In Permissive mode SELinux will only log the requests against the SELinux Policy, but will not deny any requests. Permissive mode is meant for development devices so that developers can isolate the appropriate permissions to include in the SELinux Policy before enabling Enforcing mode and shipping the device for production. While in Permissive mode the logs still capture whether a request would be allowed or denied and can be accessed through the 'dmesg' command by filtering for lines with 'avc' in them.
Possible Attack Vectors:
For a Stock device in Enforcing mode the main attack vector would be SELinux itself and the Unix standard permissions since those are the mechanisms on the device which can allow or deny full device control. This would likely require a very high degree of sophistication and social engineering since the malicious app would essentially be installing a root implementation for it to use to bypass SELinux.
For Rooted devices in Enforcing mode the main attack vectors are the root implementation and/or the user. In theory a malicious app would need to convince the user to grant it root access. From there the malicious app can utilize the tools and script locations provided by the root implementation to inject the permissions it needs for full device control. If the root implementation can be exploited directly then the malicious app may not need the user to grant root access. Another alternate attack vector could be other vulnerable apps, such as startup script compatibility apps. These apps usually require root access so the scripts are run at startup in a root context, but there is no guarantee that the location the startup scripts are placed for that app requires root access to add scripts. So a malicious app could add a script to that location and have its malicious code/permissions executed that way.
For Rooted devices in Permissive mode the main attack vectors are still the root implementation and/or the user. Except that in this situation the malicious app would never need to inject any permissions into the SELinux Policy. Instead it would only need to be granted root access to achieve full device control. The alternate attack vector also still applies.
Quick Summary (or TL;DR):
- Stock & Enforcing --> high level of security; main attack vector is SELinux implementation itself to bypass privilege escalation protection
- Rooted & Enforcing --> moderate level of security; SELinux has already been compromised, main attack vector is root implementation and/or the user in order to acquire root access for full device control, once root access is acquired inject policy permissions for full device control
- Rooted & Permissive --> low level of security; SELinux is only logging the policy requests and won't deny anything, main attack vector is root implementation and/or the user in order to acquire root access for full device control
- Stock & Permissive --> Unsure... ?
Conclusion:
Root is a responsibility and opens you to exploits and vulnerabilities which are handled with compensating controls on Stock devices. My current opinion is that running Root & Enforcing is not the same as running Root & Permissive, but it is very close since the gatekeeper to full device control becomes the root implementation & manager. An attacker needs a higher level of sophistication to interact with the appropriate tools and inject the necessary permissions. But it also shifts more responsibility onto the user since it is up to the user which apps they install and which are granted root access. Root & Enforcing mode provides protection from system attacks (such as MMS attempting to modify Network Settings) and reasonable app security provided that the user restricts root access to legitimate apps & keeps an eye on security.
Sources:
- https://source.android.com/security/selinux/
- https://android.stackexchange.com/q...elinux-is-in-permissive-mode-what-should-i-be
- https://su.chainfire.eu/#selinux-policies-supolicy
- Magisk Scripts : https://forum.xda-developers.com/showpost.php?p=68967705&postcount=2
- SuperSu Scripts : https://su.chainfire.eu/#updates-sud
The main question I wanted to answer is this:
Is being Rooted essentially the same as being in Permissive mode?
Background:
Security is always more secure in serialized layers; meaning that each layer has to be passed through one after the other. Unix provides its standard permissions as a single layer of security (for the security buffs out there this is a Discretionary Access Control system). SELinux adds an additional layer of security on top of the standard Unix Permissions by providing a Mandatory Access Control system through the enforcement of a global permissions policy. The main purpose of SELinux is to prevent escalation of privilege attacks, for example to prevent an MMS app from modifying Network Settings or accessing other resources not related to MMS. So SELinux essentially confines all apps (system or otherwise) to a realm of legitimate activity.
The SELinux Policy is actually a 'compiled' (more serialized than compiled, but it's referred to as compiled) version of a human-readable text version of the permissions contained in the policy. On a Stock Unrooted device the SELinux Policy is distributed with the ROM and is never modified except for during ROM upgrades if necessary. This provides the highest level of security (assuming the ROM provides a tight policy) since the SELinux Policy should only contain permissions for legitimate activities according to the device manufacturer and/or carrier. So SELinux would, in theory, restrict any malicious app to safe activities, preventing serious harm to your device & data.
Since the SELinux Policy restricts full access to the device in order to achieve root some of those restrictions need to be bypassed. How this is performed varies, but the end goal is the same : inject new permissions into the SELinux Policy to allow the root implementation full access to the device. If the root implementation is ethical then it should only inject permissions related to providing root access. Since root apps will likely require permissions not included in a device's Stock SELinux Policy most root implementations provide tools for injecting permissions into the SELinux Policy at runtime (selinux-inject, supolicy & magiskpolicy). Most root implementations also provide locations for startup scripts which are executed in a root context. These tools and scripts are used legitimately by the root implementation to maintain root access and by root apps to maintain stable functionality.
SELinux provides three modes : Enforcing, Permissive & Disabled (not covered in this discussion). In Enforcing mode SELinux will deny and log any requests for permissions against the SELinux Policy. Enforcing mode is meant for production devices (or devices for end users). In Permissive mode SELinux will only log the requests against the SELinux Policy, but will not deny any requests. Permissive mode is meant for development devices so that developers can isolate the appropriate permissions to include in the SELinux Policy before enabling Enforcing mode and shipping the device for production. While in Permissive mode the logs still capture whether a request would be allowed or denied and can be accessed through the 'dmesg' command by filtering for lines with 'avc' in them.
Possible Attack Vectors:
For a Stock device in Enforcing mode the main attack vector would be SELinux itself and the Unix standard permissions since those are the mechanisms on the device which can allow or deny full device control. This would likely require a very high degree of sophistication and social engineering since the malicious app would essentially be installing a root implementation for it to use to bypass SELinux.
For Rooted devices in Enforcing mode the main attack vectors are the root implementation and/or the user. In theory a malicious app would need to convince the user to grant it root access. From there the malicious app can utilize the tools and script locations provided by the root implementation to inject the permissions it needs for full device control. If the root implementation can be exploited directly then the malicious app may not need the user to grant root access. Another alternate attack vector could be other vulnerable apps, such as startup script compatibility apps. These apps usually require root access so the scripts are run at startup in a root context, but there is no guarantee that the location the startup scripts are placed for that app requires root access to add scripts. So a malicious app could add a script to that location and have its malicious code/permissions executed that way.
For Rooted devices in Permissive mode the main attack vectors are still the root implementation and/or the user. Except that in this situation the malicious app would never need to inject any permissions into the SELinux Policy. Instead it would only need to be granted root access to achieve full device control. The alternate attack vector also still applies.
Quick Summary (or TL;DR):
- Stock & Enforcing --> high level of security; main attack vector is SELinux implementation itself to bypass privilege escalation protection
- Rooted & Enforcing --> moderate level of security; SELinux has already been compromised, main attack vector is root implementation and/or the user in order to acquire root access for full device control, once root access is acquired inject policy permissions for full device control
- Rooted & Permissive --> low level of security; SELinux is only logging the policy requests and won't deny anything, main attack vector is root implementation and/or the user in order to acquire root access for full device control
- Stock & Permissive --> Unsure... ?
Conclusion:
Root is a responsibility and opens you to exploits and vulnerabilities which are handled with compensating controls on Stock devices. My current opinion is that running Root & Enforcing is not the same as running Root & Permissive, but it is very close since the gatekeeper to full device control becomes the root implementation & manager. An attacker needs a higher level of sophistication to interact with the appropriate tools and inject the necessary permissions. But it also shifts more responsibility onto the user since it is up to the user which apps they install and which are granted root access. Root & Enforcing mode provides protection from system attacks (such as MMS attempting to modify Network Settings) and reasonable app security provided that the user restricts root access to legitimate apps & keeps an eye on security.
Sources:
- https://source.android.com/security/selinux/
- https://android.stackexchange.com/q...elinux-is-in-permissive-mode-what-should-i-be
- https://su.chainfire.eu/#selinux-policies-supolicy
- Magisk Scripts : https://forum.xda-developers.com/showpost.php?p=68967705&postcount=2
- SuperSu Scripts : https://su.chainfire.eu/#updates-sud