Android Hacking, Sandboxing, & Security Exploits

SELinux Policy Analysis for Android Exploitation: Identifying and Exploiting Weak Rules

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to SELinux on Android

Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) system integrated into the Android operating system. It enforces granular permissions on all processes, files, and resources, significantly enhancing the platform’s security posture by preventing malicious or compromised applications from accessing unauthorized data or system services. While SELinux is a robust security mechanism, misconfigurations or overly permissive rules in the SELinux policy can introduce vulnerabilities, offering avenues for privilege escalation or sandbox escapes. This guide delves into the methodologies for analyzing Android’s SELinux policy to identify such weaknesses and understand how they can be exploited.

Understanding Android’s SELinux Architecture

On Android, SELinux operates in enforcing mode, meaning all unauthorized actions are blocked. The policy defines domains (representing processes or applications) and types (representing files or objects). Rules dictate which domains can access which types with specific permissions (read, write, execute, etc.). Key components include:

  • Policy File: Typically located at /sepolicy or embedded in the boot image, it contains all SELinux rules.
  • File Contexts: Defined in file_contexts, these map file paths to SELinux types, ensuring files are labeled correctly at creation or boot.
  • Process Domains: Each process runs in a specific SELinux domain (e.g., untrusted_app, system_server, platform_app), which dictates its permissions.
  • Access Vector Cache (AVC): The kernel component that performs access checks based on the loaded policy.

The core principle is that if an explicit ‘allow’ rule doesn’t exist, the action is denied.

Gathering SELinux Policy from an Android Device

The first step in analyzing SELinux policy is to retrieve it from the target device. This often requires root access or an unlocked bootloader to access system partitions.

Pulling the Policy

You can typically find the active policy file at /sys/fs/selinux/policy or /sepolicy on older devices. From a rooted device, use ADB:

adb shell
su
cp /sys/fs/selinux/policy /data/local/tmp/active_policy
exit
exit
adb pull /data/local/tmp/active_policy .

For a full policy dump from an AOSP build, you can extract the sepolicy file directly from the device’s boot.img or vendor_boot.img if you have the firmware. You might need tools like magiskboot or unpackbootimg to extract the ramdisk where /sepolicy resides.

Tools for Offline Policy Analysis

Once you have the policy file, several tools can aid in its analysis:

  • sesearch: A powerful command-line utility from the libsepol development package for querying SELinux policy rules.
  • apol: A graphical policy analysis tool, useful for visualizing complex policies.
  • sepolicy-analyze: A Python script often found in AOSP source, which can parse and query policy files.
  • Custom Scripts: Python or shell scripts using libsepol bindings or parsing textual representations can be highly effective for automated checks.

Converting Binary Policy to Text (for easier parsing)

While sesearch works directly with binary policy, for deeper analysis or custom scripting, converting it to a human-readable format can be beneficial. This requires the AOSP build environment or pre-compiled tools:

# Assuming you have the AOSP 'sepolicy-tools' in your path
# From AOSP source, you might build m4, checkpolicy, etc.
m4 -I external/sepolicy -o policy.conf external/sepolicy/sepolicy.conf
checkpolicy -M -c 30 -o binary_policy.raw policy.conf
# To 'decompile' (requires checkpolicy to generate intermediate files)
# This is more complex and often involves a full AOSP build setup.

For most practical exploitation scenarios, using sesearch against the binary policy is sufficient.

Identifying Policy Weaknesses: Techniques and Examples

1. Permissive Domains

A permissive domain logs AVC denials but does not enforce them. While rarely found in production builds for critical domains, a forgotten permissive mode for a less critical service can be a pivot point.

sesearch --allow -p permissive -t <target_policy_file>

Look for output like (permissive some_domain). If some_domain executes sensitive code or processes sensitive data, it’s a critical flaw.

2. Overly Broad allow Rules

Look for rules that grant extensive permissions or allow operations from low-privileged domains on high-privileged types.

Example: Writing to System Directories

An untrusted_app should generally not be able to write to system directories. Search for rules allowing write access to sensitive file types:

sesearch -A -s untrusted_app -t system_file -c dir -p { write create add_name } -t <target_policy_file>

If this returns an allowance for untrusted_app to write to system_file directories, an attacker could potentially plant malicious executables or configuration files, leading to privilege escalation if those files are later executed by a more privileged process.

3. Misconfigured File Contexts

File contexts define the SELinux type for files in specific paths. A misconfiguration can allow an attacker to create a file with a more powerful label than intended.

Example: Arbitrary File Type Creation

Consider a scenario where an application has write access to a directory, and the file_contexts specify a powerful type for *any* file created there.

First, identify directories writable by an unprivileged domain:

sesearch -A -s untrusted_app -c dir -p { write add_name } -t <target_policy_file>

Suppose /data/local/tmp is writable by untrusted_app. Now, check file_contexts (often in /vendor/etc/selinux/vendor_file_contexts or /etc/selinux/android/file_contexts on older devices):

# From the device
adb shell cat /vendor/etc/selinux/vendor_file_contexts | grep "/data/local/tmp"

If you find an entry like /data/local/tmp(/.*)? u:object_r:system_file:s0, it means any file created in /data/local/tmp gets the system_file label. If an attacker can then cause a privileged process to execute that system_file (e.g., via a symlink attack or path traversal), it’s a significant vulnerability.

4. Service Manager and Binder Interaction Weaknesses

Android’s Binder is crucial for inter-process communication (IPC). SELinux controls which domains can register, find, and transact with Binder services. Weaknesses here can lead to unauthorized service calls or spoofing.

Example: Unauthorized Binder Call

Search for binder_call permissions from a low-privileged domain to a sensitive service domain:

sesearch -A -s untrusted_app -t system_server -c binder -p call -t <target_policy_file>

If untrusted_app can call a service implemented by system_server (e.g., activity_service, package_service) without specific restrictions on methods, it might be possible to invoke privileged operations directly. Further analysis of the specific Binder service’s source code would be required to identify exploitable methods.

5. Domain Transitions

A domain transition allows a process to change its SELinux domain, usually after executing a specially labeled program. Misconfigured transitions can elevate privileges.

sesearch -A -s untrusted_app -p transition -t <privileged_domain> -t <target_policy_file>

If untrusted_app can directly transition to a privileged domain (e.g., system_app, init), it’s a severe vulnerability. Typically, transitions are restricted to specific executable types.

Exploitation Scenarios and Chains

Exploiting SELinux weaknesses rarely involves a single, isolated rule. Instead, it often involves chaining multiple minor misconfigurations or combining them with other kernel/userspace vulnerabilities.

  • Scenario 1: Arbitrary Write + Executable Creation: If an untrusted_app can write to a directory that gets a privileged SELinux type (via file_contexts), and a privileged process later executes files from that directory (e.g., a script in /data/vendor_app/bin that gets labeled vendor_exec), then the attacker can inject a malicious executable.
  • Scenario 2: Binder Call Abuse + Data Leak: An overly broad binder_call rule from untrusted_app to a service that handles sensitive data, combined with a method that returns too much information, could lead to data exfiltration without directly bypassing file permissions.
  • Scenario 3: Weakness in a Helper Process: A minor, often overlooked utility process might have a slightly permissive rule, allowing it to write to a location that a more privileged service then reads or executes.

Mitigation and Best Practices

For developers and security engineers, preventing these vulnerabilities requires:

  • Principle of Least Privilege: Granting only the bare minimum permissions required for a domain or process.
  • Granular Rules: Avoiding broad allow rules. Use specific types and permissions.
  • Thorough file_contexts Review: Ensure sensitive directories are correctly labeled and that unprivileged domains cannot create files with privileged labels.
  • Automated Testing: Incorporate SELinux policy analysis into CI/CD pipelines to catch regressions.
  • Regular Auditing: Periodically review the policy for unnecessary permissions, especially after system updates or new feature introductions.

Conclusion

SELinux policy analysis is a critical skill for Android security researchers and exploit developers. By systematically examining policy rules, file contexts, and domain transitions, one can uncover subtle misconfigurations that can be chained together to achieve privilege escalation or break out of an application’s sandbox. The complexity of Android’s SELinux policy necessitates a deep understanding of its components and the use of specialized tools to effectively identify and exploit its weak points, continually pushing the boundaries of Android platform security.

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 →
Google AdSense Inline Placement - Content Footer banner