A way to trigger an SELinux policy violation?

I'm studying the basic workings of SELinux and would find it useful to trigger a denial. My test machine is running CentOS 7, it's a basic server install without any extra services, and getenforce states 'Enforcing'. So I felt sure that making /root world-readable, and attempting to read files from there as an unprivileged user would do the trick. But no luck! Can anyone suggest some quick tests? Trying to access paths, or open ports, etc.

Ideally I'm looking for straightforward shell commands that a DAC wouldn't have restricted, but a MAC will notice and deny. As such I'm not looking to compile bespoke programs, or install specific services (like a web-server) to achieve this. This is valuable as it provides a generic and clear way to see SELinux in action.

I have no problem with modifying the DAC (i.e. filesystem permissions) to make them less restrictive than they would be by default as part of a test.


Solution 1:

To demonstrate SELinux's utility in bug detection for third-party / your own developer's code, here's a memory protection test (modifying the first code example here):

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>

int main (void) {
  // open file read-write, get a memory-mapped pointer with private access, write permission
  int fd = open ("file_to_test", O_RDWR);
  char *p = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

  p[0] = 'a';   // put something

  // Update protection mode; SELinux response depends on sebool: allow_execmod
  int r = mprotect (p, 42, PROT_READ | PROT_EXEC);

  // Display mprotect result
  printf ("mprotect = %d\n", r);

  close(fd);
  return 0;
}
Compile and show default (not caught)
$ echo "test data" > file_to_test
$ gcc execmod.c 

$ ./a.out 
mprotect = 0

$ sudo aureport -a

AVC Report
========================================================
# date time comm subj syscall class permission obj event
========================================================
<no events of interest were found>

Change booleans to catch the problem:

$ sudo getsebool allow_execmod
allow_execmod --> on

$ sudo setsebool allow_execmod 0
$ ./a.out 
mprotect = -1

$ sudo aureport -a

AVC Report
========================================================
# date time comm subj syscall class permission obj event
========================================================
1. 04/30/2015 12:26:41 a.out unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10 file execmod unconfined_u:object_r:user_home_t:s0 denied 3612

Solution 2:

This clearly demonstrates a MAC policy where an equivalent DAC could have been bypassed on a base install of CentOS 7.

  1. By default (in CentOS at the time of writing) unprivileged, non-system users are logged in as the 'unconfined_u' role. However we can change our system so that our unprivileged user 'alice' is placed into the 'user_u' role instead. The default policies can be made to clearly restrict this role with only a small amount of additional configuration.

    [root]# echo "alice:user_u:s0-s0:c0.c1023" >> /etc/selinux/targeted/seusers
    
  2. Now switch off the ability for these users to execute files located in their home directories and /tmp. Once again, the default is to allow this behaviour. This command may take a moment to complete.

    [root]# setsebool -P user_exec_content off
    
  3. Now (with our unprivileged user) we can log in and attempt to execute something on one of these no go areas. As you can see, we are denied.

    [alice]$ cp /bin/ls /tmp/
    [alice]$ /tmp/ls
    -bash: /tmp/ls: Permission denied
    
  4. Finally, we can view the AVC log to see our SELinux denial.

    [root]# aureport -a
    
    AVC Report
    ========================================================
    # date time comm subj syscall class permission obj event
    ========================================================
    1. 02/05/15 21:08:33 bash user_u:user_r:user_t:s0 59 file execute user_u:object_r:user_tmp_t:s0 denied 693
    

Solution 3:

Unless you have changed your policies in the Boolean tab of system-config-selinux (or in /etc/selinux/policy), then the default should respond to the following (N.B., you may also want to install setroubleshoot for a deeper dive):

mkdir -m 755 -p /install/ks

cp /root/anaconda-ks.cfg /install/ks

chmod 644 /install/ks/anaconda-ks.cfg

Then, restart your web server and attempt to access http://localhost/ks with your web browser. You should see a "Forbidden" message. If you are tailing /var/log/audit/audit.log or if you run ausearch -m avc -ts recent, then you should be able to see the message: type=AVC msg=audit(1391277951.222:266): avc: denied { read } for pid=1731 comm="httpd" name="ks" dev=sda1 ino=22351 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined u:object r:default t:s0 tclass=dir

You can then change the SELinux context with chcon -Rv --reference /var/www/html /install/ks if you did not want to disable SELinux but be able to access the resource.

EDIT: sorry, didn't see that you said "not a webserver". Try chcon -u fake_u <filename> using an unprivileged account on a system file.