The permissions and attributes on files and attributes in a Linux system ensure that only certain users can access or modify them. This is a crucial component of Linux; with this, we can achieve a higher level of security on our systems.
This tutorial will look at ways to prevent a privileged user, such as the root user, from deleting a file.
2. How Can We Limit Root Access?
Since the root user has a heightened level of access, it means that the root user can read, write, and delete any file. We can’t prevent the root user from deleting a file. This is because the root user has superuser privileges and can remove whatever configuration we make to limit its access to the system. However, we can use certain tools to restrict the root access so that we make it difficult for the root user to delete a file. Two of the options we can use to limit root access are:
- File Attributes
2.1. File Attributes
File attributes describe the properties of a file. We can view the attributes of different files by using the lsattr command:
$ lsattr -------------------- ./gogo -----a-------------- ./hello.txt ----i--------------- ./amicable.txt ...
Let’s review some of the attributes files may have on Linux systems:
- ‘c’ means that a file is automatically compressed on the disk by the kernel
- ‘a’ means that a file can only open in append mode for writing
- ‘i’ means a file is immutable or cannot be modified
- ‘e’ means a file is using extents for mapping blocks on a disk
We see that the amicable.txt file has the immutable file attribute set. Let’s see if we can delete the amicable.txt text file as the root user:
$ rm amicable.txt rm: remove regular empty file 'amicable.txt'? y rm: cannot remove 'amicable.txt': Operation not permitted
This is only possible because of the attribute set on the file. We can set a file’s attributes to be immutable by using the chattr command:
$ chattr +i hello.txt
In brief, we add the attributes to the file by using the ‘+’ symbol before the i option. Conversely, if we want to remove the attribute, we use the ‘-‘ symbol:
$ chattr -i hello.txt
Consequently, seeing that it’s possible to remove the immutable attribute from a file as root, we can’t confidently say that we can stop a root user from deleting a file using file attributes but only delay the deletion process.
SELinux, which stands for Security Enhanced Linux, is a security feature that controls access to a Linux server using security policies. It labels files and directories to control users’ access and processes on the server. Moreover, it’s possible to limit the root user’s access using SELinux because all SELinux cares about are context labels. Labels are mapped to files or directories in the format user:role:type:level, where the level field is not a compulsory parameter.
To illustrate, let’s have a look at the context labels our files and directories have:
$ ls -Z unconfined_u:object_r:user_home_dir_t:s0 admins unconfined_u:object_r:home_root_t:s0 amicable.txt unconfined_u:object_r:user_home_dir_t:s0 gogo unconfined_u:object_r:user_home_dir_t:s0 harry unconfined_u:object_r:home_root_t:s0 hello.txt
We can see the SELinux labels because of the -Z flag. A root user runs in the unconfined domain called unconfined_t or sysadm_t. Thus, an unconfined domain has a lot of privileges assigned to it.
We could limit the root user’s access to the server by changing the domain it runs in. Instead of the root user running in an unconfined domain such as unconfined_t, it can run in a restricted domain such as user_t. This would restrict the root user similarly to other non-root users.
This would mean that our root user no longer has special privileges. Although this implementation is doable, it isn’t practical. Having a root user that can’t do very much defeats its purpose.
Although limiting the root user isn’t helpful, there are some use cases where it can work in our favor. Instead of stripping away all special privileges the root user has, we can follow the Principle of Least Privilege (PoLP). This is where we can administer new privileges only for specific tasks where the root user needs elevated access. For instance, a Database Administrator wouldn’t need to interfere with services or configuration files irrelevant to their scope of work.
Thus, a Database Administrator needs superuser privileges to manage databases and the users of those databases. We can assign a user to the dbadm_r role in the dbadm_t domain. SELinux has a couple of pre-defined users that we can use.
We can view these users by using the SELinux policy information tool seinfo:
$ seinfo -u Users: 8 sysadm_u system_u xguest_u root guest_u staff_u user_u unconfined_u
To view the different roles we can map a user to, we run seinfo with the -r flag:
seinfo -r Roles: 14 auditadm_r dbadm_r guest_r logadm_r nx_server_r object_r secadm_r staff_r sysadm_r system_r unconfined_r user_r webadm_r xguest_r
Lastly, we can view the SELinux contexts of a user by running the id command while logged in as the user:
$ id -Z unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
We can use this command to verify if the context of our user has changed in the case where we were to assign the root user to a different domain and role.
In this tutorial, we explored two ways to limit root access to avoid deleting a file. We talked about how we can implement this by using file attributes and SELinux.
We acknowledged that we couldn’t prohibit the root user from deleting files. Instead, we can delay deletion. If we want to make a system more robust, we need to enforce the Principle of Least Privilege, which ensures that we use the root account for specific use cases.