2. What is Security Enhanced Linux?
â˘
â˘
⢠Security Enhanced Linux or SELinux is an
advanced access control mechanism built into
most modern Linux distributions.
It was initially developed by the US National
Security Agency to protect computer systems
from malicious intrusion and tampering.
Over time, SELinux was released in the
public domain and various distributions have
since incorporated it in their code.
2
3. What is Security Enhanced Linux?
3
â˘
â˘
⢠A properly configured SELinux system can greatly reduce security risks, and knowledge
about it can help you troubleshoot access-related error messages.
We will learn about the concepts behind SELinux: packages, commands, and configuration
files and the error messages it logs when access is denied.
We will also see a few practical instances of putting SELinux in action.
4. Who Uses SELinux?
4
⢠Available in almost all popular Linux distributions (Debian/Ubuntu, RHEL/Centos, etc.)
⢠Starting with Android 4.3, SELinux is used for tightening the boundaries of the Android
application sandbox.
â˘
â˘
â˘
Android 4.3 â Permissive Mode
Android 4.4 â Partial Enforcement Mode
Android 5.0+ - Full Enforcement Mode
(More on modes later)
5. Basic Concepts 1/2
â˘
â˘
⢠SELinux implements what's known as MAC (Mandatory Access Control). This is implemented
on top of what's already present in every Linux distribution, the DAC (Discretionary Access
Control).
In a traditional security model, we have three entities: User, Group, and Other (u,g,o) who
can have a combination of Read, Write, and Execute (r,w,x) permissions on a file or
directory.
If a user test creates a file in his/her home directory, that user will have read/write access to
it, and so will the test group. The "other" entity will possibly have no access to it.
# Run as normal user
# List contents of home directory of current user
# with help of USER environment variable
ls -lah /home/$USER
5
6. Basic Concepts 2/2
â˘
⢠test can grant (and restrict) access to these files to other users
and groups or change the owner of the files.
These actions can leave critical files exposed to accounts who
don't need this access.
⢠test can also restrict to be more secure, but that's
DISCRETIONARY: there's no way for the system administrator to
enforce it for every single file in the system.
total 16K
drwx------. 3 vagrant vagrant 95 ĐşĐ˛Ń 16 11:42 .
drwxr-xr-x. 7 root root 83 ĐşĐ˛Ń 16 11:40 ..
-rw-------. 1 vagrant vagrant 5 ĐşĐ˛Ń 16 11:42 .bash_history
-rw-r--r--. 1 vagrant vagrant 18 ĐłŃŃ 6 23:19 .bash_logout
-rw-r--r--. 1 vagrant vagrant 193 ĐłŃŃ 6 23:19 .bash_profile
-rw-r--r--. 1 vagrant vagrant 231 ĐłŃŃ 6 23:19 .bashrc
drwx------. 2 vagrant vagrant 29 ĐşĐ˛Ń 16 11:38 .ssh
6
7. Another Example
â˘
â˘
⢠When a Linux process runs, it may run as
the root user or another account with
superuser privileges.
If a hacker takes control of the application,
they can use that application to get access
to whatever resource the user account has
access to.
For processes running as the root user,
basically this means EVERYTHING in the
Linux server.
7
8. SELinux
8
â˘
⢠SELinux is a way to fine-tune access
control requirements.
With SELinux, you can define what a user
or process can do.
⢠It confines every process to its own
domain so the process can interact with
only certain types of files and other
â˘
processes from allowed domains.
This prevents a hacker from hijacking any
process to gain system-wide access.
9. SELinux Intro 1/2
9
â˘
â˘
â˘
â˘
â˘
SELinux was originally a development project from the National Security Agency (NSA ).
The NSA integrated SELinux into the Linux kernel using the Linux Security Modules
(LSM) framework. SELinux motivated the creation of LSM
Originally, the SELinux implementation used persistent security IDs (PSIDs) stored in an
unused field of the ext2 inode.
These numerical representations (non-human-readable) were mapped by SELinux to a
security context label.
This required modifying each file system type to support PSIDs.
10. SELinux Intro 2/2
10
â˘
â˘
â˘
â˘
⢠The next evolution of SELinux was as a loadable
kernel module.
This module stored PSIDs in a normal file, and
SELinux was able to support more file systems.
This solution was not optimal for performance, and
was inconsistent across platforms.
Finally, the SELinux code was integrated to the 2.6.x
kernel, which had full support for LSM and had
extended attributes (xattrs) in the ext3 file system.
SELinux was moved to using xattrs to store security
context information. The xattr namespace provides
useful separation for multiple security modules
existing on the same system.
11. Test System
⢠The commands, packages, and files that we are
going to see today will be shown on CentOS 7.
⢠The concepts remain the same for other
distributions.
⢠We will be running the commands as the root user
unless otherwise stated.
⢠If you don't have access to the root account and
use another account with sudo privileges, you need
to precede the commands with the sudo keyword.
11
12. Test System
⢠We will start with a bare installation of CentOS 7
with minimal packages installed and install
additional software on the VM with default
â˘
configurations.
We will also create a few test user accounts for
training purpose.
⢠Finaly, we will install needed SELinux-related
â˘
â˘
packages. This is to ensure we can work with the
latest SELinux commands.
To speed up the process we will use a combination
of Vagrant VM provisioner and Virtualbox VM
provider.
We will also require GIT version control system
12
13. Additional Software
13
â˘
â˘
â˘
â˘
git version control system (https://git-scm.com/downloads)
ssh client: We can use either git-bash (for windows) or native ssh client for linux/mac
Virtualbox (https://www.virtualbox.org/) for all supported platforms
Vagrant (https://www.vagrantup.com/downloads.html)
# Run as normal user
git clone https://github.com/DmyMi/lux-selinux-demo.git
cd lux-selinux-demo
vagrant up # start provisioning, will take 5-15 minutes
vagrant ssh # when provisioning is successful
14. Overview of scripts and SELinux
Packages
â˘
â˘
â˘
â˘
â˘
â˘
⢠file context
policycoreutils (provides utilities for managing SELinux)
policycoreutils-python (provides utilities for managing SELinux)
selinux-policy (provides SELinux reference policy)
selinux-policy-targeted (provides SELinux targeted policy)
libselinux-utils (provides some tools for managing SELinux)
setroubleshoot-server (provides tools for deciphering audit log messages)
setools (provides tools for audit log monitoring, querying policy, and
management)
â˘
â˘
setools-console (provides tools for audit log monitoring, querying policy, and file context
management)
mcstrans (tools to translate different levels to easy-to-understand format)
# To see all installed SELinux Packages run as root
rpm -qa | grep selinux
14
15. SELinux Modes
At any one time, SELinux can be in any of three possible modes:
⢠ENFORCING - SELinux will enforce its policy on the Linux
system and make sure any unauthorized access attempts by
users and processes are denied
â˘PERMISSIVE - is a semi-enabled state. SELinux doesn't apply
its policy in permissive mode, so no access is denied.
⢠DISABLED is self-explanatory
15
16. Checking SELinux Modes and
Status
# We can run the getenforce command to check the current SELinux mode.
# Run as either normal or super user
getenforce
# We can also run the sestatus command:
# Run as either normal or super user
sestatus
# The later should also give additional info regarding SELinux status,
# if it is enabled in either Enforcing or Permissive mode.
16
17. â˘
â˘
The main configuration file for SELinux is /etc/selinux/config
There are two directives in this file. The SELINUX directive dictates the SELinux mode
and it can have three possible values as we discussed before.
⢠The SELINUXTYPE directive determines the policy that will be used.
SELinux Configuration File
# We can run the following command to view its contents:
cat /etc/selinux/config
17
18. â˘
â˘
â˘
Enabling SELinux is fairly simple, but unlike disabling it, should be done in a two-step
process.
As a first step, we need to edit the /etc/selinux/config file to change the SELINUX
directive to permissive mode.After that we need to issue a system reboot
In the second phase, we need to edit the config file to change the SELINUX directive
from permissive to enforcing in the /etc/selinux/config file. Next, reboot the server
again.
Enable and Disable SELinux
# In permissive mode Log in to your VM again and search
# for the string "SELinux is preventing" from the contents of the /var/log/messages file.
cat /var/log/messages | grep "SELinux is preventingâ
# If there are no errors reported, we can safely move to the next step. However, it would
# still be a good idea to search for text containing "SELinux" in /var/log/messages file
cat /var/log/messages | grep "SELinuxâ
# We can also temporarily switch between enforcing and permissive modes with setenforce:
setenforce permissive
18
19. â˘
â˘
â˘
â˘
At the heart of SELinux' security engine is its policy.
A policy is a set of rules that define the security and
access rights for everything in the system.
When we say everything, we mean users, roles,
processes, and files.
The policy defines how each of these entities are
related to one another.
SELinux Policy: Terminology
19
20. ⢠SELinux has a set of pre-built users. Every regular
Linux user account is mapped to one or more
SELinux users.
⢠In Linux, a user runs a process. This can be as simple
as the user test opening a document in the text editor
(it will be test's account running the editor process) or
a service account running the httpd daemon.
⢠In the SELinux world, a process (a daemon or a
running program) is called a subject.
Users
20
21. â˘
â˘
â˘
â˘
â˘
A role is like a gateway that sits between a user and a
process.
A role defines which users can access that process.
Roles are not like groups, but more like filters: a user
may enter or assume a role at any time provided the
role grants it.
The definition of a role in SELinux policy defines which
users have access to that role. It also defines what
process domains the role itself has access to.
Roles come into play because part of SELinux
implements what's known as Role Based Access
Control (RBAC).
Roles
21
22. â˘
â˘
â˘
â˘
A subject is a process and can potentially affect an
object.
An object in SELinux is anything that can be acted
upon.
This can be a file, a directory, a port, a tcp socket, the
cursor, or even an X server.
The actions that a subject can perform on an object
are the subject's permissions.
Subjects and Objects
22
23. â˘
â˘
â˘
A domain is the context within which an SELinux
subject (process) can run.
That context is like a wrapper around the subject. It
tells the process what it can and can't do.
For example, the domain will define what files,
directories, links, devices, or ports are accessible to
the subject.
Domains for Subjects
23
24. â˘
â˘
A type is the context for a file that stipulates the file's
purpose.
For example, the context of a file may dictate that it's a
web page, or that the file belongs to the /etc directory,
or that the file's owner is a specific SELinux user.
Types for Objects
24
25. ⢠SELinux policy defines user access to roles, role access to domains, and
domain access to types.
⢠First the user has to be authorized to enter a role, and then the role has to be
authorized to access the domain. The domain in turn is restricted to access only
certain types of files.
⢠The last bit, where a process running within a particular domain can perform only
certain operations on certain types of objects, is called Type Enforcement (TE).
What is SELinux policy?
25
26. ⢠SELinux policy is not something that
replaces traditional DAC security.
⢠If a DAC rule prohibits a user access to a
file, SELinux policy rules won't be evaluated
because the first line of defense has
already blocked access.
⢠SELinux security decisions come into play
after DAC security has been evaluated.
26
SELinux Policy Behavior 1/2
27. â˘
â˘
â˘
â˘
When an SELinux-enabled system starts, the policy is
loaded into memory.
SELinux policy comes in modular format, much like the
kernel modules loaded at boot time.
And just like the kernel modules, they can be
dynamically added and removed from memory at run
time.
The policy store used by SELinux keeps track of the
modules that have been loaded.
SELinux Policy Behavior 2/2
# The sestatus command shows the policy store #
name.
# The semodule -l command lists the SELinux
# policy
# modules currently loaded into memory.
semodule -l | less
# semodule can be used for a number other
# tasks like installing, removing, reloading,
# upgrading, enabling and disabling SELinux
# policy modules.
27
28. â˘
â˘
â˘
â˘
Most modern distributions include binary versions of the modules as part of the
SELinux packages. The policy files have a .pp extension.
The .pp files are not human readable though.
The way SELinux modularization works is that when the system boots, policy
modules are combined into what's known as the active policy.
This policy is then loaded into memory.
SELinux Policy Location
# If there are any modules available â you can check them with
ls -l /etc/selinux/targeted/modules/active/modules/
# The combined binary version of this loaded policy can be found under the
# /etc/selinux/targeted/policy directory
ls -l /etc/selinux/targeted/policy/
28
29. â˘
â˘
â˘
â˘
Although you can't read the policy module files, there's a simple way to tweak their
settings.
That's done through SELinux booleans.
Changed booleans are not permanent. They revert to their old values after a reboot.
To make things permanent, we can use the -P switch with the setsebool command.
Changing SELinux Boolean Settings
# Show the different switches that can be turned on or off,
# what they do, and their current statuses.
semanage boolean -l | less
# To change any of the settings, we can use the setsebool command
# check
getsebool ftpd_anon_write
# set
setsebool ftpd_anon_write on
# check again
getsebool ftpd_anon_write
29
30. â˘
30
The SELinux policy for the application will determine what types of
files it needs access to and what processes it can transition to.
⢠The first part of security puts a label on each entity in the Linux
system.
⢠A label is like any other file or process attribute (owner, group, date
created etc.) it shows the context of the resource.
⢠Context is a collection of security related information that helps
SELinux make access control decisions.
SELinux for Processes and Files
31. Before we go any further, here is a note about SELinux naming
convention:
â˘SELinux Users are suffixed by "_uâ
â˘SELinux Roles are suffixed by â_râ
â˘SELinux Types (for files) or SELinux Domains (for processes) are
suffixed by "_t".
31
Naming Conventions
32. ⢠Let's start by understanding SELinux file contexts.
â˘
â˘
â˘
We now have an extra column of information after the user and group ownership.
This column shows the security contexts of the files.
A file is said to have been labelled with its security context when you have this
information available for it
SELinux File Contexts 1/2
# regular ls -l command against the /etc directory
ls âl /etc
# now add the -Z flag
ls âZ /etc
32
33. ⢠Let's take a closer look at one of the security contexts.
⢠The first part is the SELinux user context for the file. We will discuss SELinux users
later, but for now, we can see that it's system_u.
⢠The second part specifies the SELinux role, which is object_r.
⢠What's most important here is the third part, the type of the file that's listed here as
etc_t. This is the part that defines what type the file or directory belongs to.
⢠The fourth part of the security context, s0, has to do with multilevel security or MLS.
SELinux File Contexts 2/2
ls âZ /etc | grep yum.conf
ls âZ /etc | grep locale.conf
33
34. ⢠Let's now talk about process security contexts.
â˘
â˘
â˘
The security context has four parts: user, role, domain, and sensitivity.
The user, role, and sensitivity work just like the same contexts for files.
The domain is unique to processes.
SELinux Process Contexts
# Restart the Apache and SFTP services
systemctl restart httpd && systemctl restart vsftpd
# We can run the ps command with a few flags to show the Apache and SFTP processes running
ps -efZ | grep 'httpd|vsftpd'
34
35. â˘
35
â˘
â˘
â˘
So far we have seen that files and processes can have different contexts, and that
they are restricted to their own types or domains.
To run, a process needs to access its files and perform some actions on them (open,
read, modify, or execute).
We have also learned that each process can have access to only certain types of
resources (files, directories, ports, etc.).
SELinux stipulates these access rules in a policy. The access rules follow a standard
allow statement structure
⢠Class defines what the resource actually represents (file, directory, symbolic link,
device, ports, etc.)
How Processes Access Resources
allow <domain> <type>:<class> { <permissions> };
36. ⢠Let's consider the security contexts of the httpd daemon running on our system
Ex. #1: Apache httpd 1/3
# The default home directory for the web server is /var/www/html.
# Let's create a file within that directory and check its context
touch /var/www/html/index.html
ls -Z /var/www/html/*
# We can use the sesearch command to check the type of access allowed for the httpd daemon
sesearch --allow --source httpd_t --target httpd_sys_content_t --class file
# The flags used with the command are fairly self-explanatory:
-the source domain is httpd_t (the domain Apache is running in)
-We are interested about target resources that are classified as files
-and have a type context of httpd_sys_content_t.
# Notice the line
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
# This says that the httpd daemon (the Apache web server) has I/O control, read, get attribute,
# lock, and open access to files of the httpd_sys_content_t type.
# In this case our index.html file has the same type.
36
37. ⢠Let's first modify the web page /var/www/html/index.html
â˘
â˘
Lets try to access it in our browser: http://127.0.0.1:8080
The httpd daemon is authorized to access a particular type of file and we can see it
when accessing via the browser.
Ex. #1: Apache httpd 2/3
nano /var/www/html/index.html
37
# Place the following content into the file:
<html>
<title>
This is a test web page
</title>
<body>
<h1>Hello Luxembourg Security :)</h1>
</body>
</html>
# Next, we will change the permission of the
# /var/www/ folder and its contents, followed by
# a restart of the httpd daemon
chmod -R 755 /var/www
systemctl restart httpd
38. â˘
â˘
Let's make things a little different by changing the context of the file.
We will use the chcon command for it.
⢠When we try to access the web page (i.e. the httpd daemon tries to read the file),
you may get a Forbidden error, or you may see the generic CentOS "Testing 123"
page.
⢠To make things work again, let's change the file type with the restorecon command.
Ex. #1: Apache httpd 3/3
# The --type flag for the command allows us to specify a new type for the target resource.
# We are changing the file type to var_t
chcon --type var_t /var/www/html/index.html
# Confirm the change
ls -Z /var/www/html/
38
# The -v switch shows the change of context labels
restorecon -v /var/www/html/index.html
39. â˘
â˘
â˘
SELinux enforces something we can term as "context inheritance". What this
means is that unless specified by the policy, processes and files are created with the
contexts of their parents.
So if we have a process called "proc_a" spawning another process called "proc_b",
the spawned process will run in the same domain as "proc_a" unless specified
otherwise by the SELinux policy.
Similarly, if we have a directory with a type of "some_context_t", any file or directory
created under it will have the same type context unless the policy says otherwise.
Context Inheritance for Files and
Directories
# Check directory
ls -Z /var/www
# Copy to another directory
cp /var/www/html/index.html /var/
# Check file
ls -Z /var/index.html
# This change of context can be overridden by the --preserver=context clause
# in the cp command.
# Now move and check
mv /var/index.html /etc/
ls -Z /etc/index.html
39
40. Ex. #2: File Context Error
#
# Relax access to content within /var/www.
#
<Directory "/var/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
# Create new directory and check its context (should be default_t)
mkdir -p /www/html && ls -Z /www/
# Copy our website . It should get the default_t type
cp /var/www/html/index.html /www/html/
# Edit Apache config
nano /etc/httpd/conf/httpd.conf
# Find the following section and change it (starts at line 119)
# to look like right snippet
# then restart Apache using command: systemctl restart httpd
DocumentRoot "/var/www/html"
DocumentRoot "www/html"
#
# Relax access to content within /var/www.
#
<Directory "/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
40
41. â˘
â˘
â˘
We saw two commands for changing file contents: chcon and restorecon. Running
chcon is a temporary measure.
Running chcon requires you to know the correct context for the file, as the --type
flag specifies the context for the target.
restorecon doesn't need this specified. If you run restorecon, the file will have the
correct context re-applied and the changes will be made permanent.
⢠But if you don't know the file's correct context, how does the system know which
context to apply when it runs restorecon?
Changing and Restoring SELinux
File Contexts 1/2
# extract from one of the files
cat /etc/selinux/targeted/contexts/files/file_contexts | less
41
42. â˘
â˘
â˘
â˘
To permanently change the context of our test file (index.html) file under /www/html,
we have to follow a two-step process
First, we create our context binding using semanage command
Second, we will use restorecon to apply all the required contexts
Now we know a few more useful commands
Changing and Restoring SELinux
File Contexts 2/2
# Step 1: Set file contexts for both directories
semanage fcontext --add --type httpd_sys_content_t "/www(/.*)?"
semanage fcontext --add --type httpd_sys_content_t "/www/html(/.*)?"
# Check if contexts are added
cat /etc/selinux/targeted/contexts/files/file_contexts.local
# Step 2: restorecon with recursive(-R) flag
restorecon -Rv /www
# Verify the correct context before and after restorecon
matchpathcon -V /www/html/index.html
42
43. ⢠So far we have seen how processes access file system resources.
⢠Domain transition is the method where a process changes its context from one domain to
another.
⢠The case of domain transition is fairly common in SELinux.
Domain Transition
43
44. ⢠Letâs consider the systemd process. This is the ancestor of all processes and runs
within a context of init_t
Domain Transition Example
# Check system context
ps -eZ | grep init
# Check vsftpd binary context
ls -Z /usr/sbin/vsftpd
# Check vsftpd process
ps -eZ | grep vsftpd
44
45. Domain transition is subject to three strict rules:
â˘The parent process of the source domain must have the execute permission for the application
sitting between both the domains (this is the entrypoint).
â˘The file context for the application must be identified as an entrypoint for the target domain.
â˘The original domain must be allowed to transition to the target domain.
45
Domain Transition Rules
46. ⢠Taking the vsftpd daemon example, let's run the sesearch command with different
switches to see if the daemon conforms to these three rules.
Domain Transition Rule Example
# See if source domain has execute permission on entry point
# flags: -s â source, -t â target, -c â class, -p â permission,
# -A â allow rules, -d â direct name match
sesearch -s init_t -t ftpd_exec_t -c file -p execute âAd
# Check if binary is entry point for target domain
sesearch -s ftpd_t -t ftpd_exec_t -c file -p entrypoint âAd
# Check if there is a transition permission
sesearch -s init_t -t ftpd_t -c process -p transition -Ad
46
47. â˘
47
â˘
We compared domain to a hypothetical bubble around the process: something that stipulates what
the process can and can't do.
This is what confines the process.
⢠SELinux also has processes that run within unconfined domains.
⢠Example of an unconfined process domain would be unconfined_t.
Unconfined Domains
48. â˘
48
SELinux users are different entities from normal Linux user accounts, including the root
account.
⢠The user names end with _u, just like types or domain names end with _t and roles end
with _r.
⢠Different SELinux users have different rights in the system and that's what makes them
useful.
⢠When SELinux is enforced, each regular Linux user account is mapped to an SELinux user
account.
SELinux Users 1/4
49. â˘
â˘
There are only three listed here, though we've created a few more during VM
provisioning?!
New users are represented by the entry shown as default.
SELinux Users 2/4
# To view user
semanage login
mapping
âl
Login Name SELinux User MLS/MCS Range Service
default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
49
50. ⢠What does this bigger table mean?
SELinux Users 3/4
# See what SELinux users are available in the system
semanage user âl
50
SELinux User
Labeling
Prefix
MLS/
MCS Level
MLS/
MCS Range SELinux Roles
guest_u
root
staff_u
sysadm_u
system_u
unconfined_u
user_u
xguest_u
user
user
user
user
user
user
user
user
s0
s0
s0
s0
s0
s0
s0
s0
s0
s0-s0:c0.c1023
s0-s0:c0.c1023
s0-s0:c0.c1023
s0-s0:c0.c1023
s0-s0:c0.c1023
s0
s0
guest_r
staff_r sysadm_r system_r unconfined_r
staff_r sysadm_r system_r unconfined_r
sysadm_r
system_r unconfined_r
system_r unconfined_r
user_r
xguest_r
51. ⢠Demonstration of unconfined access by regular users
We had seen the list of a number of SELinux users before:
â˘
â˘
â˘
â˘
⢠guest_u: This user doesn't have access to X-Window system (GUI) or networking and can't
execute su / sudo command.
xguest_u: This user has access to GUI tools and networking is available via Firefox browser.
user_u: This user has more access than the guest accounts (GUI and networking), but can't switch
users by running su or sudo.
staff_u: Same rights as user_u, except it can execute sudo command to have root privileges.
system_u: This user is meant for running system services and not to be mapped to regular user
accounts.
SELinux Users 4/4
# run as root user
id -Z
# Go to GUI and log in as regular user (login: reguser & password: regpass)
# run same command
id -Z
51 Letâs change the default behavior
52. ⢠Mind you though, it still doesn't stop people from logging in directly as the high-
privileged user with login & password
⢠But if you set up a passwordless SSH connection with RSA keypair for every user â
it can help protect your server even if the password for regular user is known to a
hacker.
Restricting User Access
# Use Vbox GUI
# The regular user switches to the switched user account.
# We assume he knows the password for switched user (itâs swpass )
su â swuser
# Go to root user terminal
# (-a â add a record of specified type, -s SEUSER â SELinux user type)
semanage login -a -s user_u reguser
# update contexts
restorecon -RFv /home/reguser/
52
53. Restricting Access to Services
# As root user stop Apache
systemctl stop httpd
# Go to GUI and log in as restricted user (login: restuser & password: respass)
# assume he doesnât know root password
systemctl start httpd
# Go to GUI after adding to sudoers
sudo systemctl start httpd
# in root terminal
semanage login -a -s user_u restuser
# verify user_u access to roles and user_r role access to domains (root terminal)
# There are a number of httpd related domains, but httpd_t is not one of them.
seinfo -uuser_u âx
seinfo -ruser_r -x | grep httpd
# as restricted user try to start httpd again
sudo systemctl start httpd
nano /etc/sudoers
# in the file, add the
# following line,
# save and exit
restuser ALL=(ALL) ALL
53
54. ⢠You can set all new users to be mapped to user_u by default
â˘
â˘
â˘
â˘
Restricting is boring. What if we want to permit a user to do something?
We have to use a more permissive role or âŚ
We have to write our own role with all the required permissions, which requires deep
understanding of available permission checks, reference policy macros and more.
It is out of the scope of this intro
Changing the Default Mapping
# -m â modify a record of specified object
# -r â security range for MLS/MCS
semanage login -m -S targeted -s "user_u" -r s0 default
# verify with
semanage login -l
# more permissive role
semanage login -a -s "sysadm_u" guestuser
# update contexts
restorecon -RFv /home/guestuser/
54
55. New Role Example
policy_module(pgsql_admin, 1.0)
# Define the pgsql_admin_r role
role pgsql_admin_r;
# Create a pgsql_admin_t type that has minimal rights a regular
# user domain would need in order to work
# on a Linux system
userdom_base_user_template(pgsql_admin)
# Allow the pgsql_admin_t type to execute regular binaries (f.i. id)
corecmd_exec_bin(pgsql_admin_t)
# Allow the user domain to read its own selinux context
selinux_getattr_fs(pgsql_admin_t)
# Allow the user to administer postgresql, but do not fail
# if no postgresql SELinux module is loaded yet
optional_policy('
postgresql_admin(pgsql_admin_t, pgsql_admin_r)
')
# To allow transition from staff_r to pgsql_admin_r
gen_require('
role staff_r;
')
allow staff_r pgsql_admin_r;
55
56. â˘
â˘
â˘
While administering your system, you would be interested to look at the error
messages logged by SELinux.
These messages are logged in specific files and they can provide detailed
information about access denials.
In a CentOS 7 system you can look at two files
SELinux Audit Logs 1/3
/var/log/audit/audit.log
/var/log/messages
56
# The first command is ausearch. We can make use of this command if the auditd daemon is running.
# For example, letâs check our Apache server, -m â message, -c â command (process) name
ausearch -m avc -c httpd
57. ⢠In our system a number of entries might be listed, but we will concentrate on the next
one
SELinux Audit Logs 2/3
type=SYSCALL msg=audit(1489938539.297:155): arch=c000003e syscall=4 success=no exit=-13 a0=7ffb8aab4130 a1=7ffe02c56fb0 a2=7ffe02c56fb0
a3=ffffff00 items=0 ppid=22187 pid=22189 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295
comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1489938539.297:155): avc: denied { getattr } for pid=22189 comm="httpd" path="/var/www/html/index.html"
dev="dm-0" ino=67359616 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file
⢠To understand it, let's take apart each of the fields
57
58. â˘
â˘
â˘
â˘
â˘
â˘
â˘
â˘
â˘
type=AVC and avc: AVC stands for Access Vector Cache.
denied { getattr }: The permission that was attempted and the result it got. In this case the get
attribute operation was denied.
pid=22189. This is the process id of the process that attempted the access.
comm: The process id by itself doesn't mean much. The comm attribute shows the process
command. In this case it's httpd. Immediately we know the error is coming from the web server.
path: The location of the resource that was accessed. In this case it's a file under
/var/www/html/index.html.
dev and ino: The device where the target resource resides and its inode address.
scontext: The security context of the process. We can see the source is running under the httpd_t
domain.
tcontext: The security context of the target resource. In this case the file type is var_t.
tclass: The class of the target resource. In this case it's a file.
SELinux Audit Logs 3/3
type=AVC msg=audit(1489938539.297:155): avc: denied { getattr } for pid=22189 comm="httpd"
path="/var/www/html/index.html" dev="dm-0" ino=67359616 scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:var_t:s0 tclass=file
58
59. An SELinux denial can be corrected in different ways
â˘Correct a wrong label on the source domain or the target resource. If not using the
defaults, you will probably need to do this
â˘Change an SELinux Boolean. Many applications behaviour can be modified this way
â˘Use the application as it was intended
â˘Add a new rule that allows the denial. Only if all of the above are not applicable!
59
Usual Ways to Fix the Errors?
60. â˘
â˘
We can also use the sealert tool.
This command can be used with the id value of the error message logged in the
/var/log/messages file
Understanding the Error
# Check if there are any errors in the logs
cat /var/log/messages | grep "SELinux is preventing"
# Check detailed info about the error
sealert -l <your-error-id>
# Or we can use audit2why that parses the logs and shows the reason in readable form
# first lets search the logs for todayâs errors with ausearch and pipe it to audit2why
# -ts â time stamp to start the search
ausearch -m avc -ts today | audit2why
60
62. ⢠Edit SFTP config file and uncomment anon_upload_enable=YES
Step #1
# Open SFTP Config file
nano /etc/vsftpd/vsftpd.conf
# find and uncomment the line anon_upload_enable=YES
# Restart SFTP
systemctl restart vsftpd
# Run the lftp cli
lftp
# open the connection to localhost
lftp> open 127.0.0.1
# try to upload a file
lftp> put .bashrc -o pub/.bashrc
# try to figure why we encounter an error
# hint use ls command
lftp> ls -lah pub/
62
63. ⢠Wrong DAC settings. No write permission
⢠To solve it â exit the lftp client and change permission
Step #1: Solved
drwxr-xr-x
drwxr-xr-x
2 0
3 0
0
0
6 Nov 05 19:43 .
17 Apr 16 11:39 ..
chmod 777 /var/ftp/pub/
63
64. ⢠Try uploading again
Step #2
# Run the lftp cli
lftp
# open the connection to localhost
lftp> open 127.0.0.1
# try to upload a file
lftp> put .bashrc -o pub/.bashrc
# try to figure why we encounter ANOTHER error
# hint use ausearch command
ausearch -m avc -c vsftpd
# or sealert on the latest entry in logfile
tail /var/log/messages -n 4 | grep "SELinux is preventing"
sealert -l <error-id>
# or audit2why
ausearch -m avc -c vsftpd | audit2why
64
65. ⢠MAC error ftpd_t domain cannot write to public_content_t type. Confirm it by
running
⢠sealert proposes two fixes:
Step #2: Solved
turn
# Proposed Fix no. 1
# If you want to allow vsftpd to be able to write to shared public content
# Then you need to change the label on pub to public_content_rw_t, and potentially
on # the allow_httpd_sys_script_anon_write boolean.
# Do
semanage fcontext -a -t public_content_rw_t pub
restorecon -R -v pub
setsebool -P allow_ftpd_anon_write 1
# Proposed Fix no. 2
#You can generate a local policy module to allow this access.
#Do
#allow this access for now by executing:
ausearch -c 'vsftpd' --raw | audit2allow -M my-vsftpd
semodule -i my-vsftpd.pp
sesearch --allow --source ftpd_t --target public_content_t -d
65
66. â˘
â˘
It can generate SELinux policy allow/dontaudit rules from logs of denied operations
Usually this generated policy is very unsecure
Mostly used flags are:
â˘
â˘
â˘
-M â generate compiled and loadable SELinux module,
-a â get all from raw input,
-m â generate uncompiled module (type enforcement file)
⢠Then we can view and compile this module with checkmodule
⢠Finally we can package the compiled policy using semodule_package and installed
audit2allow
ausearch -c 'vsftpd' --raw | audit2allow -a -m my-vsftpd > my-vsftpd.te
66
# -M â MLS enabled, -m â non-base policy (can be added to existing policy), -o - output
checkmodule -M -m -o my-vsftpd.mod my-vsftpd.te
semodule_package -o my-vsftpd.pp -m my-vsftpd.mod
semodule -i my-vsftpd.pp
67. â˘
67
Set up a test environment and enable SELinux in Permissive mode
⢠Launch an application that needs a policy
⢠Extensively use the application and most of itâs features for a long period of time
(hours, days)
⢠Use audit2allow to generate a policy from security log
⢠Review the policy and remove/modify unnecessary permissions
⢠Use the policy in production
audit2allow General Workflow
68. SELinux policy consists of six components:
â˘Type enforcement (TE) attributes
â˘TE type declarations
â˘TE transition rules
â˘TE change rules (not used much)
â˘TE access vector rules
â˘File context specifications
These components are stored in type enforcement file (.te).
68
Creating Custom Policy
69. â˘
â˘
69
Identify sets of types with similar properties.
SELinux does not interpret these attributes.
Attributes
# Their format is
attribute <name>
# For example
attribute logfile;
attribute privuser;
70. â˘
70
Define type names, with optional aliases and attributes.
TE Type Declarations
# Their format is
type <name> [alias <aliases>] [attributes]
# For example
type mailman_log_t, file_type, sysadmfile, logfile;
type man_t alias catman_t;
71. ⢠Specify allowed type transitions.
71
That can be read as:
⢠When a process running in the mysqld_t domain accesses a socket labeled with the
mysql_db_t type, transition to the mysqld_var_run_t domain.
TE Transition Rules
# Their format is
type_transition <source> <action> <target>
# For example
type_transition mysqld_t mysql_db_t:sock_file mysqld_var_run_t;
72. ⢠Specify the new type to use when relabeling, based on process domain, object type,
and object class
72
That can be read as:
⢠When running in the rssh_t domain, relabel the associated terminal device as a user
terminal
TE Change Rules (Optional)
# Their format is
type_change <source> <action> <target>
# For example
type_change rssh_t server_ptynode:chr_file rssh_devpts_t;
73. ⢠Specify the set of permissions based on a type pair and an object security class
73
Where <kind> can be one of:
â˘
â˘
â˘
â˘
allow â allow requested access
auditallow â allow requested access and log the access
dontaudit â donât allow and donât log
neverallow â stop compilation of policy
TE Access Vector Rules 1/3
# Their format is
<kind> <source> <target>:<securityclass> <permissions>
74. Can be read as:
â˘Processes running in the initrc_t domain have get-attribute, read, and execute access
to files of type account_exec_t
74
Can be read as:
â˘Processes running in the traceroute_t domain do not log the denial of a request for
name_bind permission on a tcp_socket for all types associated to the port_type
attribute (except port_t)
TE Access Vector Rules 2/3
# example
allow initrc_t acct_exec_t:file { getattr read execute };
# example
dontaudit traceroute_t { port_type -port_t }:tcp_socket name_bind;
75. Can be read as:
â˘Processes running in the ada_t domain log the granting of a request to execute code
located on the process stack.
75
Can be read as:
â˘No subsequent allow rule can permit the shadow password file to be read, except for
those rules associated with the can_read_shadow_passwords attribute.
â˘This rule is intended to be used during the compilation of policy files, not to protect a
running system.
TE Access Vector Rules 3/3
# example
auditallow ada_t self:process { execstack execmem };
# example
neverallow ~can_read_shadow_passwords shadow_t:file read;
76. â˘
â˘
â˘
â˘
Define default contexts for files.
These components are stored in file context file (.fc)
Type is optional and can be left blank.
When it is filled, it is similar to the mode field for the ls command. The -d means to
match only directories, the -- means to match only files.
File Context Specifications
# Their format is
<name-reg-exp> [file-type][security-context]
76
# For example
/bin/login -- system_u:object_r:login_exec_t:s0
/var/tmp/logcheck
/etc/tripwire(/.*)?
-d system_u:object_r:logrotate_tmp_t
system_u:object_r:tripwire_etc_t
78. ⢠For this practical example we will use a simple java application Jnode
This simle application represents a typical aplication we can have on a server:
78
â˘
â˘
â˘
â˘
â˘
it uses network,
connects to the database,
reads config files,
writes data to tmp files,
monitors its state (cpu, memory and disk)
a Policy for Test
Creating
Application
79. Why do we need so many types?
Because all of them represent different categories of system access
Type Enforcement File: jnode.te
policy_module(jnode, 1.0.0)
# process domain
type jnode_t;
# type for executable file
type jnode_exec_t;
# type for config files
type jnode_conf_t;
# type for caching (i.e. /var/cache/)
type jnode_cache_t;
# type for log file
type jnode_log_t;
# type for temporary files
type jnode_tmp_t;
# type for the port that the application listens to (using binkp protocol)
type binkp_port_t;
79
80. Whatâs Next?
Easy way:
â˘audit2allo
w Hard way:
â˘Manual configuration of all permissions
â˘Can use predefined macros to help (still doesnât make it easy )
# Macros location
/usr/share/selinux/devel/include/
# contains quite a few *.if` files with default macrosâ
# for SELinux base policy and their description
# Example
cat /usr/share/selinux/devel/include/system/userdomain.if
80
81. â˘
â˘
â˘
If you remember the attribute concept - some kind of container for types, that can
has special access rules too.
It means that if we add our new type to some kind of attribute we automaticaly will
have default rights for that attribute.
There are some predefined macros to allocate types to attribute, so you don't have
to memorize them all
Attribute Macros
# For config files
files_config_file(jnode_conf_t)
# For misc files
files_type(jnode_cache_t)
# For log files
logging_log_file(jnode_log_t)
# For temp files
files_tmp_file(jnode_tmp_t)
# For ports
corenet_port(binkp_port_t)
81
82. â˘
â˘
Default Permission Macros 1/2
When we have all the types defined, we can set the default behaviour to our
application.
You can find them in the *.if files easily using keywords
# Application macros: adds jnode_t type to the list of applications
# and allows it to be launched by jnode_exec_t type
application_domain(jnode_t, jnode_exec_t)
# Daemon macros: adds jnode_t type to the list of daemons,
# allowing it to be launched by systemd and sets the transition:
# if systemd launches the file with jnode_exec_t type, then the process
# receives the jnode_t type
init_daemon_domain(jnode_t, jnode_exec_t)
# Allows the jnode_t type execute standard binary files ( /bin, /usr/bin )
corecmd_exec_bin(jnode_t)
# Allows the jnode_t type to use libraries
libs_use_ld_so(jnode_t)
# Allows the jnode_t type to read the system status ( cpu, memory )
kernel_read_system_state(jnode_t)
# Allows the jnode_t type to write to /tmp
files_rw_generic_tmp_dir(jnode_t)
# Allows the jnode_t type to read the network config files (i.e., /etc/resolv.conf)
sysnet_read_config(jnode_t)
82
83. Default Permission Macros 2/2
# Allows the jnode_t type to read random numbers from /dev/(u)random
dev_read_rand(jnode_t)
# Allows the jnode_t type to read file ssystem attributes ( free disk space )
fs_getattr_xattr_fs(jnode_t)
# Allows the jnode_t type to do dns resolve
sysnet_dns_name_resolve(jnode_t)
# Allows the jnode_t type to read /var/log ( read_only )
logging_search_logs(jnode_t)
# Sets the rule: log files created by jnode_t process
# will have the jnode_log_t type
logging_log_filetrans(jnode_t, jnode_log_t, file)
# Sets the rule: tmp-files created by jnode_t process
# will have the jnode_tmp_t type
files_poly_member_tmp(jnode_t, jnode_tmp_t)
# Allows jnode_t to execute bind() to any address
corenet_tcp_bind_generic_node(jnode_t)
# Allows jnode_t to communicate with postgresql over unix-socket
postgresql_stream_connect(jnode_t)
# Allows jnode_t to communicate with postgresql over network
corenet_tcp_connect_postgresql_port(jnode_t)
83
84. â˘
â˘
File Contexts
Now it is time to bind the new types to file system.
Lets create the File Contexts file jnode.fc
# Executable File
/opt/jnode/jnode.run -- gen_context(system_u:object_r:jnode_exec_t)
# Everything that needs to be read_only for the service
# we can move to the "config"
/opt/jnode(/.*)?
/opt/jnode/jar(/.*)
gen_context(system_u:object_r:jnode_conf_t)
gen_context(system_u:object_r:jnode_conf_t)
# And the configs them self
/opt/jnode/point/.*.cfg gen_context(system_u:object_r:jnode_conf_t)
# The service will have permission to write files here,
# but will no be able to not remove them
/opt/jnode/fileechoes(/.*)? gen_context(system_u:object_r:jnode_cache_t)
/opt/jnode/point(/.*)? gen_context(system_u:object_r:jnode_cache_t)
# Here is the folder for any temporary files and folders our service generates
/opt/jnode/(inbound|temp)(/.*)? gen_context(system_u:object_r:jnode_tmp_t)
# And here we will store the log files
/var/log/jnode(/.*)? gen_context(system_u:object_r:jnode_log_t)
84
85. ⢠Now we are ready to compile our module.
Compilation and installation
# Switch to the folder containing jnode.te and jnode.fc
sudo make -f /usr/share/selinux/devel/Makefile
To install the module we can use
sudo semodule -i jnode.pp
# to enable it
sudo semodule -e jnode
# Now we can set any port for our binkp_port_t type, for example
sudo semanage port -a -t binkp_port_t -p tcp 24554
# finaly change the file contexts according to contexts file
sudo restorecon -Rv /opt/jnode
# Check if rules applied
sesearch --allow -s jnode_t -d
85
86. ⢠Now we are ready to compile our module.
Final audit2allow
# Now we can start the service
cd /opt/jnode/bin/ && sudo bash /opt/jnode/bin/run.sh &
# Application should be accessible at: http://127.0.0.1:8082/index.html
# After app activity
audit2allow -b -r -t jnode_t
86