sudo-project / sudo

Utility to execute a command as another user
https://www.sudo.ws
Other
1.17k stars 210 forks source link

Enforce SELinux type and role in sudoers. (proof of concept) #176

Closed freedge closed 2 years ago

freedge commented 2 years ago

At the moment a SELinux type and role can be defined in a sudoers file. They help confined users who want to elevate privileges to a confined administrator role: they can just type sudo without adding --role and --type on the command line. The command line arguments take precedence over the values in the sudoers though.

Now outside the SELinux login world, considering a usecase where admins need to grant some privileges to normal users, they will need to carefully craft the right sudo rules. The command provided to the user will run in an unconfined SELinux context, with all the root capabilities, so the glob or regexp pattern must be written with no mistake. The NOEXEC tag helps mitigating errors but is limited to blocking execve system calls.

It should be possible to leverage SELinux: by enforcing the role and type provided in the sudoers file, and writing a custom SELinux policy module, I find that it is possible to give a normal, not confined user, rights to run commands in a specific SELinux context, greatly reducing the error surface.

Here is an example of such module (mostly copy pasted from what Udica generates for containers):

(block auditor
(type process)
(type socket)
(roletype system_r process)
(typeattributeset domain (process ))
(typeattributeset container_domain (process ))
(typeattributeset svirt_sandbox_domain (process ))
(typeattributeset mcs_constrained_type (process ))
(typeattributeset file_type (socket ))
(allow process socket (sock_file (create open getattr setattr read write
rename link unlink ioctl lock append)))
(allow process proc_type (file (getattr open read)))
(allow process cpu_online_t (file (getattr open read)))
)

That can be installed with

semodule -i auditor.cil

To make sudo behavior backward compatible, in this proof of concept we prefix the type and role with an asterisk to indicate it should take precedence over arguments given on the command line. The sudoers ends up looking like this:

auditor ALL = (root) TYPE=*auditor.process ROLE=*unconfined_r NOPASSWD: /usr/bin/bash

We observe the impact of this policy as files like /etc/passwd or /etc/shadow are unreadable.

This is just a proof of concept wrote after briefly researching the subject. Maybe I missed something more fundamental. Also maybe it is possible to write an approval plugin to achieve the same behavior, but I had some troubles getting the Python plugin framework to work on Fedora so I did that instead... Feedback welcome!

freedge commented 2 years ago

it will be more easy to develop a plugin (example)