How Can I Protect SELinux Labels From Being Modified?

As revWhiteShadow, and as a contributor to the revWhiteShadow personal blog site, we understand the critical importance of maintaining the integrity of SELinux labels, especially in security-sensitive environments like Fedora 23 with SELinux enabled and enforced. The ability to modify file labels with tools like restorecon and chcon undeniably presents a potential bypass for security policies. Let’s explore how to harden your system against unauthorized label modifications, leveraging both SELinux’s built-in capabilities and Fedora’s targeted policy.

Understanding the Threat: Label Modification as a Security Weakness

The foundation of SELinux’s Mandatory Access Control (MAC) lies in its labels. These labels define the security context of every process, file, and resource on the system. Modifying these labels, especially to more permissive values, effectively undermines the security policy.

Imagine a scenario where a malicious actor gains limited access. By changing the SELinux label of a critical system binary to a more permissive type, they could escalate their privileges significantly. For instance, a file labeled with user_home_t might be modified to system_exec_t, allowing an attacker to execute arbitrary code with system-level permissions. Therefore, preventing unauthorized label modification is crucial for maintaining a robust security posture.

Leveraging Fedora’s Targeted Policy and Security Booleans

Fedora’s targeted policy offers several booleans designed to enhance security and prevent unwanted modifications. While secure_mode, secure_mode_insmod, and secure_mode_policyload contribute to overall system hardening, they don’t directly address the problem of user space processes arbitrarily modifying SELinux labels using tools like chcon. These booleans primarily focus on restricting privilege escalation and kernel module manipulation.

  • secure_mode: This boolean focuses on preventing transitions to privileged roles like sysadm_t, often associated with sudo and su. While helpful in limiting privilege escalation, it doesn’t directly prevent label modifications by processes already running within a specific context.

  • secure_mode_insmod: This boolean aims to prevent the loading of kernel modules, which is a common attack vector. However, it does not affect the ability of processes to manipulate existing SELinux labels.

  • secure_mode_policyload: This boolean prevents processes from modifying the active SELinux policy. This is a crucial safeguard against persistent policy changes, but it doesn’t restrict the use of tools like chcon to alter individual file labels in the short term.

Therefore, while enabling these booleans is highly recommended as part of a broader security strategy (using setsebool -P <boolean_name> 1), they are not the primary solution for preventing unauthorized label modification.

Hardening SELinux Against Label Modification: Capabilities and Type Enforcement

The key to preventing unauthorized label modification lies in a combination of SELinux capabilities, proper type enforcement rules, and file context configurations. We will need to craft custom policies.

1. Understanding SELinux Capabilities and chcon

The chcon utility, by default, relies on the dac_override and dac_read_search capabilities, meaning that even if SELinux is enforcing, users can change file contexts if they have the necessary permissions to override DAC (Discretionary Access Control) rules, which are the traditional Unix file permissions. To truly restrict label modification, we must prevent even root from arbitrarily changing labels.

We can achieve this by creating a custom SELinux policy module that restricts the ability of processes to use chcon and similar tools. This involves writing an SELinux policy module and loading it into the system.

Here’s a step-by-step approach:

  1. Identify the Target Processes: Determine which processes you want to restrict. For example, you might want to restrict all processes running in the unconfined_t domain from using chcon.

  2. Create a Type Enforcement (TE) Rule: This rule will prevent the targeted processes from executing chcon. Create a new file, for example, no_chcon.te, with the following content:

module no_chcon 1.0;

require {
    type unconfined_t;
    type bin_t;  # Type for executables in /bin, /usr/bin, etc.
    class file execute;
}

# Prevent unconfined processes from executing chcon
deny unconfined_t bin_t:file execute;
**Explanation:**

*   `module no_chcon 1.0;`: Declares the module name and version.
*   `require { ... }`: Defines the required types and classes.
*   `type unconfined_t;`:  Specifies the type for processes running in the unconfined domain.
*   `type bin_t;`: Specifies the type typically assigned to executables in standard binary directories.
*   `class file execute;`: Specifies the permission to execute a file.
*   `deny unconfined_t bin_t:file execute;`: **This is the crucial rule.** It denies processes running in the `unconfined_t` domain from executing any file with the `bin_t` type.
  1. Compile the Policy Module: Use the checkmodule and semodule_package utilities to compile the policy module.
checkmodule -M -m -o no_chcon.mod no_chcon.te
semodule_package -o no_chcon.pp -m no_chcon.mod
  1. Load the Policy Module: Load the compiled policy module into the SELinux kernel.
semodule -i no_chcon.pp
  1. Test the Policy: Try running chcon from a process running in the unconfined_t domain (e.g., a regular user’s shell). You should receive a permission denied error.

  2. Customize for Specific Domains: Adapt the policy by replacing unconfined_t with the specific SELinux types you want to restrict. For example, to restrict a custom domain my_app_t, replace unconfined_t with my_app_t in the policy.

3. Restricting Label Changes to Specific Domains

Instead of completely blocking chcon, you might want to restrict label changes to only specific, authorized domains. This approach allows designated system processes to modify labels while preventing unauthorized modifications.

  1. Identify Authorized Domains: Determine which SELinux domains should be allowed to modify labels. For example, you might allow processes running as systemd_t or a custom service domain.

  2. Grant Specific Permissions: Create policy rules that allow these authorized domains to use the setattr permission on files and directories. This permission is necessary for changing SELinux labels.

Here’s an example policy snippet:

module allow_label_changes 1.0;

require {
    type systemd_t;
    class file setattr;
    class dir setattr;
    attribute file_type;  # Base type for all files
    attribute dir_type;   # Base type for all directories
}

# Allow systemd_t to change labels on files and directories
allow systemd_t file_type:file setattr{ relabelto relabelfrom };
allow systemd_t dir_type:dir setattr{ relabelto relabelfrom };

Explanation:

  • type systemd_t;: Specifies the type for systemd processes.
  • class file setattr;: Specifies the setattr permission for files, which includes the ability to change SELinux labels.
  • class dir setattr;: Specifies the setattr permission for directories.
  • allow systemd_t file_type:file setattr { relabelto relabelfrom };: Allows processes running as systemd_t to change labels on any file with the file_type attribute. relabelto and relabelfrom specifically grant the ability to change a file’s label.
  • allow systemd_t dir_type:dir setattr { relabelto relabelfrom };: Allows processes running as systemd_t to change labels on any directory with the dir_type attribute.

Compile and load this policy module as described in the previous section. Remember to adjust the types and classes to match your specific requirements.

4. Protecting File Context Configuration Files

SELinux uses file context configuration files (e.g., /etc/selinux/targeted/contexts/files/file_contexts) to determine the default labels for files. Protecting these files from unauthorized modification is crucial.

  1. Ensure Proper Ownership and Permissions: Verify that these files are owned by root and have appropriate permissions (e.g., 0644).

  2. Protect with SELinux: Ensure that these files have the correct SELinux labels. Typically, they should be labeled with policy_config_t. You can verify this with ls -Z /etc/selinux/targeted/contexts/files/file_contexts.

  3. Restrict Modification: Create a policy rule that prevents unauthorized processes from modifying these files.

module protect_file_contexts 1.0;

require {
    type unconfined_t;
    type policy_config_t;
    class file write;
}

# Prevent unconfined processes from writing to policy configuration files
deny unconfined_t policy_config_t:file write;

This policy prevents processes running in the unconfined_t domain from writing to files labeled with policy_config_t. Adjust the types as needed for your environment.

5. Using Extended Attributes to Enhance Label Integrity

SELinux stores labels as extended attributes on filesystems that support them (e.g., ext4, XFS). You can enhance label integrity by ensuring that the filesystem is mounted with the user_xattr option. This allows SELinux to properly manage and protect the extended attributes containing the labels.

Verify that your filesystem is mounted with user_xattr by checking /etc/fstab or running mount.

Example Implementation for a Specific Use Case

Let’s assume you have a web application running in a custom SELinux domain httpd_app_t and you want to prevent it from using chcon to modify file labels.

  1. Create a Policy Module: Create a file named no_httpd_chcon.te with the following content:
module no_httpd_chcon 1.0;

require {
    type httpd_app_t;
    type bin_t;
    class file execute;
}

# Prevent httpd_app_t from executing chcon
deny httpd_app_t bin_t:file execute;
  1. Compile and Load the Module:
checkmodule -M -m -o no_httpd_chcon.mod no_httpd_chcon.te
semodule_package -o no_httpd_chcon.pp -m no_httpd_chcon.mod
semodule -i no_httpd_chcon.pp

Now, any process running in the httpd_app_t domain will be unable to execute chcon.

Monitoring and Auditing SELinux Label Modifications

Even with these protections in place, it’s essential to monitor and audit SELinux label modifications to detect any suspicious activity.

  1. Auditd Rules: Use auditd to log attempts to modify SELinux labels. Create audit rules that monitor the setattr syscall and the execution of chcon.

Here’s an example audit rule:

auditctl -w /usr/bin/chcon -p x -k selinux_label_modification
auditctl -a always,exit -F arch=b64 -S lsetfilecon,fsetfilecon -k selinux_label_modification

This rule logs any execution of chcon and any calls to the lsetfilecon and fsetfilecon syscalls, which are used to set file context labels.

  1. Log Analysis: Regularly analyze your audit logs for events related to SELinux label modifications. Look for unexpected or unauthorized changes.

Caveats and Considerations

  • Impact on System Functionality: Restricting label modification can impact system functionality if not done carefully. Ensure that your policies are well-defined and only restrict the necessary domains.

  • Maintenance Overhead: Custom SELinux policies require ongoing maintenance. Keep your policies up-to-date and adjust them as your system evolves.

  • Complexity: SELinux policy writing can be complex. Use the available tools (e.g., audit2allow) to simplify the process and generate policy rules from audit logs.

  • Restorecon and Relabeling: After implementing restrictions, consider how restorecon will function. It may be necessary to allow certain processes to use restorecon to correct labels. Ensure that you limit this capability only to trusted processes.

By implementing these measures, you can significantly enhance the security of your Fedora 23 system by preventing unauthorized modification of SELinux labels. Remember to thoroughly test your policies and monitor your system for any unexpected behavior.