Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
redhat:base-redhat:selinux-redhat [2018/05/08 11:01] – [SELinux Access Control] michael | redhat:base-redhat:selinux-redhat [2018/05/08 11:22] (current) – [Multi-Category Security (MCS)] michael | ||
---|---|---|---|
Line 155: | Line 155: | ||
Although the default configuration of the targeted policy is to use unconfined logins, the administrator can quite easily switch to the **Role-Based Access Control** model. This model also switches to ' | Although the default configuration of the targeted policy is to use unconfined logins, the administrator can quite easily switch to the **Role-Based Access Control** model. This model also switches to ' | ||
- | FIXME | + | < |
+ | # semanage login -a -s " | ||
+ | </ | ||
+ | |||
+ | The semanage-login command maps a Linux username to an SELinux user named " | ||
+ | |||
+ | < | ||
+ | # sudo -r sysadm_r -i | ||
+ | </ | ||
+ | |||
+ | This can be automated by adding a configuration file under / | ||
+ | |||
+ | <sxh plain; gutter: false;> | ||
+ | %wheel | ||
+ | </ | ||
+ | |||
+ | It is still possible to login as an unconfined user or switch to the unconfined role via **newrole**, | ||
+ | |||
+ | < | ||
+ | # semanage user -a -R " | ||
+ | </ | ||
+ | |||
+ | Then substituting staff_u for my_staff_u in the semanage-login command. Now attempting to switch to the unconfined_r role will result in an **AVC** and **SELINUX_ERR** message. If the admin wishes to remove the ability to login as an unconfined user completely, they should remap the __default__ login to a more suitable SELinux user, again using semanage-login. | ||
+ | |||
+ | < | ||
+ | # semanage login -m -s " | ||
+ | </ | ||
+ | |||
+ | If a user wishes to login as a role other than their default it is up to the login program to provide this functionality. SSH allows logging in with an alternative SELinux role by specifying it as part of the login identifier (e.g., as a staff user logging in as unconfined_r). | ||
+ | |||
+ | < | ||
+ | # ssh < | ||
+ | </ | ||
+ | |||
+ | The strict model that comes with Role-Based Access Control isn't perfect from a perspective of least privilege; running a quick search using policy analysis tools we can see that several confined programs can still read a users private SSH keys. | ||
+ | |||
+ | <WRAP center box 100%> | ||
+ | < | ||
+ | # sesearch -ACS -t ssh_home_t -c file -p read | ||
+ | </ | ||
+ | |||
+ | <sxh plain; gutter: false;> | ||
+ | Found 132 semantic av rules: | ||
+ | allow snapperd_t file_type : file { ioctl read getattr lock open } ; | ||
+ | allow oddjob_mkhomedir_t user_home_type : file { ioctl read write create getattr setattr lock append unlink link rename open } ; | ||
+ | allow mplayer_t non_security_file_type : file { ioctl read getattr lock open } ; | ||
+ | allow sendmail_t user_home_type : file { ioctl read getattr lock open } ; | ||
+ | allow systemd_tmpfiles_t non_auth_file_type : file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename open } ; | ||
+ | allow login_pgm ssh_home_t : file { ioctl read getattr lock open } ; | ||
+ | allow ssh_keygen_t ssh_home_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ; | ||
+ | allow colord_t user_home_type : file { read getattr } ; | ||
+ | ... snip ... | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | |||
+ | Beyond the strict model, Role-Based Access Control also provides a mechanism for limiting the scope of what a user can do when they use **sudo** to switch to root. It is often desirable to enforce least privilege on users with specific roles like DBAs or auditors and the targeted policy includes several user roles for purposes like those, with documentation in their respective manual pages as mentioned in Policy Documentation. | ||
+ | |||
+ | <WRAP center box 100%> | ||
+ | < | ||
+ | # seinfo -r | ||
+ | </ | ||
+ | <sxh plain; gutter: false;> | ||
+ | Roles: 14 | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | To map a user to one of these admin roles, the same semanage-user command is used as before to create a new SELinux user associated with the desired roles, and then semanage-login to associate the Linux login with the SELinux user. If the user should also be able to start system daemons they administrate from their user domain (i.e., to start mysql as dbadm_r for debugging from a shell) the system_r role should be included in their list of associated roles. | ||
+ | |||
+ | < | ||
+ | # semanage user -a -R " | ||
+ | # semanage login -a -s " | ||
+ | </ | ||
==== Multi-Category Security (MCS) ==== | ==== Multi-Category Security (MCS) ==== | ||
+ | |||
+ | Multi-Category Security provides a way to associate a set or range of **compartments** with SELinux contexts. The targeted policy model implements compartmentalization of types associated with mcs_constrained_type. To understand how this works, it's required to know how to inspect the MLS part of security contexts. This is the part after the user: | ||
+ | |||
+ | <sxh plain; gutter: false;> | ||
+ | system_u: | ||
+ | ▼ ▼ | ||
+ | Low security level, | ||
+ | associated with no | ||
+ | compartments. | ||
+ | </ | ||
+ | |||
+ | One thing that is noticeable above is the lack of compartments on the low security level, as well as both security levels being the same. The first point is an implementation detail of the MCS model in the targeted policy. When an access vector is computed for a process that is associated with mcs_constrained_type, | ||
+ | |||
+ | The compartment part of the above security context is a **category range**, but can also be a set of categories separated by commas. A range of categories results in the context being associated with an inclusive set of categories in that range. Understanding how access is computed for two processes with a set of categories requires looking at the **dominance** rules for SELinux security levels (access is only allowed if the source type's high security level **dominates** the target type's high security level). Those rules are as follows (only accounting for categories, and not MLS security levels) | ||
+ | |||
+ | * Source dominates the target if the categories in the source context are the same as or a superset of those in the target context. | ||
+ | * Source is dominated by the target if the categories in the source context are a subset of the categories of the target context. | ||
+ | * Source and target are equal and dominate each other if the set of categories are the same in each context. | ||
+ | |||
+ | With that in mind, we know that a context with a category set of c0.c5 will be granted access to a context with a category set of c0,c3, but not a category set of c0,c6, or c0.c1023. This rule is the reason that sVirt generates a random set of categories, so there will be no overlap where one virt domain will dominate another. The Android project also does the same thing, to put applications in isolated domains. | ||
+ | |||
+ | An example use of Multi-Category Security could be using NGINX with multiple vhosts that connect to backend servers that are also running as httpd domains (e.g., PHP-FPM). Normally these instances of the backend servers would be able to modify and manage each others domains simply due to type-enforcement rules. If they' | ||
+ | |||
+ | There are a couple of presequities to achieving this. First, '' | ||
+ | |||
+ | <WRAP center box 100%> | ||
+ | < | ||
+ | # seinfo -xamcs_constrained_type | ||
+ | </ | ||
+ | <sxh plain; gutter: false;> | ||
+ | | ||
+ | netlabel_peer_t | ||
+ | openshift_t | ||
+ | openshift_app_t | ||
+ | sandbox_min_t | ||
+ | sandbox_x_t | ||
+ | sandbox_web_t | ||
+ | sandbox_net_t | ||
+ | svirt_t | ||
+ | svirt_tcg_t | ||
+ | svirt_lxc_net_t | ||
+ | svirt_qemu_net_t | ||
+ | svirt_kvm_net_t | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | To add to this list of types it is necessary to create a local policy module that associates the desired type with the attribute. This is done using the typeattribute statement, and can be done like so: | ||
+ | |||
+ | <sxh plain; gutter: false;> | ||
+ | policy_module(httpd_mcs, | ||
+ | gen_require(` | ||
+ | type httpd_t; | ||
+ | attribute mcs_constrained_type; | ||
+ | ') | ||
+ | |||
+ | typeattribute httpd_t mcs_constrained_type; | ||
+ | </ | ||
+ | |||
+ | See FIXME Customizing Local Policy for instructions on building policy modules. | ||
+ | |||
+ | Once the type is associated with mcs_constrained_type each backend server must have their content relabeled to include the respective categories in their file context specifications. This can be achieved by adding the file types to / | ||
+ | |||
+ | < | ||
+ | # semanage fcontext -a -t httpd_sys_content_t -r " | ||
+ | # semanage fcontext -a -t httpd_sys_content_t -r " | ||
+ | </ | ||
+ | |||
+ | The next step is making sure the backend servers are started with the correct security context. On CentOS 7 with systemd this can be achieved with the '' | ||
+ | |||
+ | < | ||
+ | # runcon " | ||
+ | </ | ||
+ | |||
+ | Or in the systemd unit: | ||
+ | |||
+ | <sxh plain; gutter: false;> | ||
+ | SELinuxContext=system_u: | ||
+ | </ | ||
+ | |||
+ | Now each backend server should be isolated from the other, while allowing NGINX access to manage and send messages to both of them. | ||
Line 162: | Line 329: | ||
https:// | https:// | ||
- | |||