Selinux
This document is written for RHEL based systems
helper tools
setools-console
CLI tool collectionsetroubleshoot-server
setools
GUI collectionsetroubleshoot
GUI collectionpolicycoreutils-devel
switch selinux on
# show status
$ sestatus
...
SELinux status: enabled
...
Current mode: permissive
Mode from config file: permissive
# check config file
> cat /etc/selinux/config
...
SELINUX=permissive
# switch to 'enforcing' and reboot system
# check status again
$ sestatus
...
SELinux status: enabled
...
Current mode: enforcing
Mode from config file: enforcing
NOTE: When switching from disabled
to enforcing
, the whole filesystem needs to be relabels’d first.
Reason for this is that the folders and files created in disabled mode arn’t labeled yet.
# paste an empty file
> touch /.autorelabel
# or use dedicated cmd, which will creating the file
> fixfiles -F onboot
# reboot system
policy types
Find policy-type settings in /etc/selinux/config
Policy | Description |
---|---|
Targeted This | Policy applies Access Controls to Proccesses that they are often targeted by attacking. (Default) |
MLS | Multilevel Security Policy. It implements Bell-LaPadula (BLP) model and possible to apply more complex controls. |
...
SELINUXTYPE=targeted
Default policy on Almalinux 9 is default
.
To change the policy-type we need to ensure first that the target policy-file is already installed.
In our case the mls - Multi Level Security protection
package:
# install mls policy-file
> dnf -y install selinux-policy-mls
# this will install the 'mls' files in the selinux config folder
> ls -1t /etc/selinux/
...
mls
config
targeted
semanage.conf
Change SELINUXTYPE=
to mls
, relabel filesystem and reboot the host.
NOTE: ensure that your
SELINUX=
mode is set topermissive
Additional Notes
- The default RHEL/AlmaLinux policy forces MCS with only
s0
sensitivity. - MLS enforces the
Bell-La Padula
Mandatory Access Model. - No desktop support when using MLS due to missing X-server support.
selinux context
Attribute | Description |
---|---|
SELinux User | Mapped to an SELinux user by policy, for each Linux user. |
Role | Defines SELinux user roles and controls access to domains via policy (RBAC). |
Type | Defines process domains and file types (TE). |
Level | Supports sensitivity:category syntax (MLS/MCS), with options including s0 sensitivity and c0-c1023 categories. |
# show file context using '-Z' option
$ ls -Z /etc/os-release
...
system_u:object_r:etc_t:s0 /etc/os-release
Value | Attribute |
---|---|
system_u | SELinux User |
object_r | Role |
etc_t | Type |
s0 | Level |
The ‘Z’ option can be set for many programs
# show process context using 'Z' option
$ ps axZ
...
system_u:system_r:kernel_t:s0 2 ? S 0:00 [kthreadd]
Some usual SELinux contexts
Value | Attribute |
---|---|
unconfined | unconfined process or file, not handled by SELinux |
kernel_t | kernel thread or module |
sysadm_t | system administration tools (e.g. RPM, YUM) |
httpd_t | HTTP server process (Apache, Nginx, etc.) |
var_t | variable files (e.g. /var, /usr/local) |
log_t | log files (e.g. system logs, application logs) |
container_runtime_t | container runtime environment (e.g. Docker) |
sshd_t | SSH daemon process |
booleans
By using SELinux booleans, you can fine-tune your system’s security configuration.
# show booleans, filter 'http'
$ getsebool -a | grep http
...
httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
# install 'semanage'
> dnf install policycoreutils-python-utils
# use 'semanage' to describe booleans
$ semanage boolean -l
...
httpd_anon_write (off , off) Allow httpd to anon write
httpd_builtin_scripting (on , on) Allow httpd to builtin scripting
httpd_can_check_spam (off , off) Allow httpd to can check spam
httpd_can_connect_ftp (off , off) Allow httpd to can connect ftp
Changing a boolean
We want to allow the boolean httpd_can_network_connect
# get current status
> getsebool httpd_can_network_connect
...
httpd_can_network_connect --> off
# switch boolean off using 'setsebool'
> setsebool -P httpd_can_network_connect on
# or switch boolean off using 'semanage'
> semanage boolean -m httpd_can_network_connect --on
# get status
> getsebool selinuxuser_ping
...
httpd_can_network_connect --> on
file-context handling
First, all file
context’s are stored in /etc/selinux/targeted/contexts/files/*
To change a file context we can use chcon
or semanage
. But using these commands requires a restorecon
command as well to save the change.
Lets imagin you saved a certificate file on the server by transfering it to your user directory and move it to /etc/pki/tls/certs
.
The filecontext will looks like this: unconfined_u:object_r:user_home_t:s0
This file-context is not allowed to be used as certicicate, we need to add at least the cert_t
context.
chcon
Option | Attribute |
---|---|
-u | SELinux User |
-r | Role |
-t | Type |
# change file context
> chcon -t cert_t /etc/pki/tls/certs/foo.crt
# save state
> restorecon /etc/pki/tls/certs/foo.crt
# change full-context
> chcon \
-u system_u \
-r object_r \
-t cert_t \
/etc/pki/tls/certs/foo.crt
# copy context from reference file
> chcon --reference=/foo /bar
semanage
# change file context
> semanage fcontext -a -t cert_t /etc/pki/tls/certs/foo.crt
# when changing the context a second time, switch '-a' to '-m'
> semanage fcontext -m -t cert_t /etc/pki/tls/certs/foo.crt
port handling
# print services and ports, filter for 'http_port'
> semanage port -l | grep http_port
...
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
# add port to 'http_port'
> semanage port -a -t http_port_t -p tcp 7474
# print services and ports, filter for '7474'
> semanage port -l | grep 7474
...
http_port_t tcp 7474, 3000, 80, 81, 443, 488, 8008, 8009, 8443, 9000
log analysis
Trigger AVC
AVC stands for Access Vector Cache.
In SELinux, AVC uses predefined rules called “tecs” (Type Enforcement Policies) to determine whether an access request is allowed or denied.
SELinux’s AVC checks if the request matches any of the predefined rules. If it does, the access is allowed; if not, it’s denied.
# install httpd
> dnf install httpd
# stop webserver
> systemctl stop httpd
# switch httpd listen port to 7575
> sed -i 's/Listen\ 80/Listen\ 7575/g' \
/etc/httpd/conf/httpd.conf
# start webserver
> systemctl start httpd
...
Job for httpd.service failed ...
log files
- /var/log/audit/audit.log
- /var/log/messages
debug commands
Action | Effect |
---|---|
aureport --avc | print auditd messages |
ausearch -m avc | search for avc alerts |
ausearch -m avc -ts today | show for today’s avc alerts |
journalctl -t setroubleshoot | using systemd-journald |
sealert -a /var/log/audit/audit.log | generate nice in detail report, contains hints to handle the alerts |
sealert -l dac41341-6fff-4e1d-a903-9491ec490213 | print details including instruction for action, fetch the uuid from /var/log/messages |
grep 'avc: .denied' /var/log/audit/audit.log | grep for avc denies in /var/log/audit/audit.log |
grep setroubleshoot /var/log/messages | grep for setroubleshoot preventions in /var/log/messages |
allow rules
To allow denied actions we can builf our own policy to spefically allowing them.
generate policy
To generate a rules created from the audit alerts we can use package policycoreutils-devel
This package holds the sepolicy
command which can help to perform the initial steps.
See more details in the RHEL documentation:
manually build
terms
.te
type enforcement file: A plain text file contains SELinux policy rules.
.mod
module file: A binary modul generated from the .te
file.
.pp
policy package file: The final policy to apply generated from the .mod
file.
# define the target eg. `ssh`
> p=ssh
# View AVC denials and pipe them through `audit2allow -l`
> grep $p /var/log/audit/audit.log |\
audit2allow -l
# Same as above but generating the `.te` type enforcement file.
> grep $p /var/log/audit/audit.log |\
audit2allow -l -v -m local_$p > local_$p.te
# Build a binary module `.mod` from the type enforcement file.
> checkmodule -M -m -o local_$p.mod local_$p.te
# Build the `.pp` policy package from the `.mod` file
> semodule_package -o local_$p.pp -m local_$p.mod
# Install the new `.pp` policy module
> semodule -v -i local_$p.pp
Sometimes multiple iterations of starting the application and running the policy commands are required to get the final result.
There is already a script available.
policy tools
sediff
Compare two policies to find differences.seinfo
List policy components.sesearch
Search rules (allow, type_transition, etc.)
command explanation
Command | Explanation |
---|---|
sestatus | Displays the status of SELinux, including whether it is enabled or disabled, what policy is currently in use, etc. |
semanage | Provides a command-line interface for managing SELinux policies and configuration. |
getenforce | Returns the current mode of SELinux (Enforcing, Permissive, or Disabled). |
setenforce | Changes the mode of SELinux without a system reboot, switches between Enforcing and Permissive modes. |
restorecon | Restores the default SELinux security contexts for files and directories. |
chcon | Changes SELinux security context of a file or directory manually. |
sealert | Parses and analyzes SELinux AVC denials and produces a human-readable explanation and solution if one exists. |
ausearch | Searches through the audit logs for specific events. Can be used to find all SELinux denials. |
sesearch | Searches through SELinux policies for specific entries. |
semodule | Manages SELinux policy modules. |
audit2why | Provides an explanation of SELinux denials in logs. |
audit2allow | Generates SELinux policy allow rules from logs of denied operations. |
ps -eZ | Lists all running processes with their SELinux security contexts. |
ls -Z | Displays security contexts of files and directories. |
id -Z | Displays user’s SELinux context. |
newrole -r <role> | Switch roles within a logged-in shell. This requires the user to have role-switching rights in the policy. |
runcon -c <context> | Run a program in a different SELinux security context. |
seinfo | Provides detailed information about the loaded SELinux policy. |
setsebool | Sets the current values of SELinux booleans. Booleans allow parts of SELinux policy to be changed at runtime without requiring modifications to or recompilation of policy sources. |
disable selinux
beside of switching the mode in /etc/selinux/config
to disable its also possible to modify boot parameters:
# disbale selinux and reboot
> grubby --update-kernel ALL --args selinux=0
# re-enable selinux and reboot
> grubby --update-kernel ALL --remove-args selinux