Introduction to Android SELinux and its Role
Android’s security architecture relies heavily on Security-Enhanced Linux (SELinux), a mandatory access control (MAC) system that operates alongside traditional discretionary access control (DAC). Introduced in Android 4.3, SELinux enforces fine-grained permissions on processes, files, and other system resources, effectively compartmentalizing the operating system and limiting the damage potential of compromised applications. Every process runs within a specific SELinux domain, and every file or resource has an associated SELinux type. Interactions between domains and types are governed by a strict policy, which is loaded at boot time.
While SELinux significantly enhances Android’s security posture, its complexity means that policy misconfigurations or overly broad rules can introduce vulnerabilities. Reverse engineering these policies is a critical skill for security researchers and penetration testers aiming to uncover privilege escalation paths, sandbox escapes, and other exploitation opportunities.
Understanding Android SELinux Policy Structure
An Android SELinux policy is a collection of rules written in a specialized language, defining types, attributes, domains, and the allowed interactions between them. Key components include:
- Types: Labels applied to objects (files, processes, sockets) representing their security context.
- Domains: Special types applied to processes, defining their execution context.
- Classes: Categories of system objects (e.g.,
file,process,socket,service). - Permissions: Actions that can be performed on objects (e.g.,
read,write,execute,bind). - Rules: Directives like
allow,neverallow,type_transition,role, defining the policy logic.
Our goal in reverse engineering is to analyze these rules to find weaknesses that a malicious actor or a compromised application could exploit to gain unauthorized access or elevate privileges beyond its intended scope.
Extracting the SELinux Policy from an Android Device
Before analysis, we need the policy file itself. There are two primary methods to obtain it:
1. From a Running Device (Root Required)
If you have root access to an Android device, the active policy can be pulled directly from the `/sys` filesystem.
adb shellsu -c 'cat /sys/fs/selinux/policy > /sdcard/sepolicy'adb pull /sdcard/sepolicy .
This method provides the currently loaded policy, which might include dynamic modifications made at runtime, although these are typically minimal.
2. From the Boot Image
For a more comprehensive analysis, extracting the policy from the boot image is often preferred, as it represents the policy shipped with the device firmware. The SELinux policy is typically located within the ramdisk portion of the boot.img or vendor_boot.img (for devices using A/B partitions).
- Obtain the Boot Image: Download the factory image for your device, or extract
boot.img/vendor_boot.imgfrom a device backup. - Unpack the Boot Image: Use tools like
magiskbootorAOSP bootimg toolsto unpack the image. - Locate the Policy: The policy file is usually named
sepolicyand found in the root of the extracted ramdisk (e.g.,ramdisk/sepolicy).
magiskboot unpack boot.img
Analyzing the SELinux Policy for Flaws
Once you have the sepolicy file, specialized tools are essential for parsing and querying its complex structure.
1. Using sepolicy-analyze (from AOSP/SETools)
sepolicy-analyze is a powerful command-line utility from the AOSP source or the setools suite. It allows detailed queries about policy rules, domains, and types.
- List all domains:
sepolicy-analyze -s sepolicy_file domain_list - List all types:
sepolicy-analyze -s sepolicy_file type_list - Query permissions for a specific domain and target type:
This is crucial for understanding what a process (domain) can do to a resource (type). For example, checking what
untrusted_app(a common domain for installed apps) can do tozygote:sepolicy-analyze -s sepolicy_file query perms untrusted_app zygote - Find all `allow` rules involving a specific type:
Useful for understanding how a particular resource is accessed.
sepolicy-analyze -s sepolicy_file query rules type_name
2. Using apol (SETools)
apol provides a graphical interface for exploring SELinux policies, which can be very helpful for visualizing relationships between types, domains, and rules.
apol sepolicy_file
Within apol, you can navigate through domains, types, and rules, inspect their attributes, and view the graph of allowed transitions and accesses. This visual representation often helps in spotting unusual or overly broad permissions quickly.
Identifying Common Policy Flaws for Exploitation
When analyzing policies, look for patterns that could be exploited:
1. Overly Permissive allow Rules
An allow rule that grants excessive permissions can be a direct path to exploitation. For example, an application’s domain (e.g., untrusted_app) should not have write access to critical system files or executable memory.
# Example of a potentially dangerous allow ruleallow untrusted_app system_file:file { execute execute_no_trans read write entrypoint };
If untrusted_app can write to a system_file and then execute it, it can achieve arbitrary code execution as the system_server (if system_file is actually accessible to untrusted_app and writable in a way that allows a type transition or direct execution).
2. Type Confusion and Mislabeling
Sometimes, system resources are mislabeled with an incorrect SELinux type, granting a less privileged domain access it shouldn’t have. For instance, if a critical system daemon’s configuration file is accidentally labeled as app_data_file instead of a more restrictive type, an untrusted app might gain read/write access.
# Scenario: Configuration file for a privileged service is mislabeled.adb shell ls -Z /data/misc/service_configs/critical_service.confu:object_r:app_data_file:s0 /data/misc/service_configs/critical_service.conf
An untrusted_app often has broad permissions over app_data_file, potentially leading to configuration tampering for a privileged service.
3. Improper Domain Transitions and Privileged Executables
The type_transition rule allows a process to transition to a new SELinux domain when executing a specific file. If a low-privileged domain can execute a file that transitions it to a high-privileged domain, this is a clear path to privilege escalation.
# Example of a dangerous type_transition rule.type_transition untrusted_app system_file:process system_server;
This rule would allow an untrusted_app to transition to the system_server domain merely by executing a system_file labeled as a process, effectively granting it root-like privileges.
Another common flaw involves the execmem permission. If a domain (especially a low-privileged one) has execmem, it can execute code from memory segments it has allocated and written to. This is a powerful primitive for arbitrary code execution.
# Query for execmem permissions for untrusted_appsepolicy-analyze -s sepolicy query perms untrusted_app self:process execmem
If this returns an allow rule, it means untrusted_app can use mmap with PROT_EXEC, which is often a critical step in traditional memory corruption exploits to gain code execution.
A Practical Scenario: Exploiting a Permissive `execmem`
Scenario Setup
Imagine we have an untrusted_app that discovers a policy flaw: its domain, untrusted_app, is explicitly allowed execmem permission.
allow untrusted_app self:process { execmem };
Policy Discovery
Using sepolicy-analyze, we confirm the permission:
sepolicy-analyze -s sepolicy_file query perms untrusted_app self:process execmemFound rule:allow untrusted_app untrusted_app:process { execmem };
Exploitation Steps (Conceptual)
- Develop Shellcode: Create a small piece of ARM/ARM64 shellcode that performs a desired action, such as spawning a shell or writing to a protected file.
- Allocate Executable Memory: The Android application (running as
untrusted_app) usesmmapto allocate a memory region withPROT_READ | PROT_WRITE | PROT_EXECpermissions. Theexecmempermission allows this. - Execute Shellcode: The application then casts the memory region to a function pointer and executes it. Because
execmemis allowed, this operation succeeds, and the shellcode runs within the context of theuntrusted_appdomain. Depending on what the shellcode does, this can lead to further exploitation, such as gaining access to resources theuntrusted_appshould not control (e.g., if shellcode targets a vulnerable service or a mislabeled file).
/* Example: ARM64 shellcode to execute /system/bin/id */char shellcode[] = "x01x00x00x00" // ADRP X0, #offset_to_string"xe2x03x00x91" // ADD X0, X0, #offset_in_page"x00x00x00x00" // STR X0, [SP, #0] (placeholder for syscall args)"x01x01x00xd4" // SVC #0x80 (syscall number for execve)"x00x00x00x00" // .string "/system/bin/id" (placeholder, adjust for actual string)
#include <sys/mman.h>void *mem = mmap(NULL, sizeof(shellcode), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);if (mem == MAP_FAILED) { // Handle error}memcpy(mem, shellcode, sizeof(shellcode));((void (*)())mem)(); // Execute the shellcode
Mitigation and Best Practices
For developers and system integrators, understanding these attack vectors is key to building more secure Android systems:
- Principle of Least Privilege: Grant only the absolute minimum permissions required for a domain to function.
- Strict Type Labeling: Ensure all files and resources are correctly labeled with the most restrictive types possible.
- Avoid `execmem`: Explicitly deny
execmemfor all but the most trusted and critical components. - Regular Policy Audits: Periodically review and audit SELinux policies, especially after updates or custom modifications.
- Automated Analysis Tools: Integrate tools like
sepolicy-analyzeinto the CI/CD pipeline to catch overly permissive rules early.
Conclusion
Reverse engineering Android SELinux policies is a challenging but rewarding endeavor for security professionals. By systematically extracting and analyzing the policy rules, and understanding common misconfigurations, it’s possible to identify significant security vulnerabilities. The ability to unearth and understand these policy flaws provides crucial insights into the real-world security posture of Android devices and helps in developing more robust and resilient systems against sophisticated attacks.
Android Mobile Specs & Compare Directory
Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!
Compare Devices Specs →