16

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.

bwDraco
  • 45,747
  • 43
  • 165
  • 205
Thoughtitious
  • 323
  • 1
  • 8
  • 2
    +1 knowing how to trigger your protective systems so that you can verify they're functioning is a vital and oft-missed step. – gowenfawr Apr 30 '15 at 17:53
  • I'm voting to close this question as off-topic because it belongs on Unix&Linux SE. – Mark May 01 '15 at 02:06

4 Answers4

5

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
ǝɲǝɲbρɯͽ
  • 308
  • 1
  • 8
  • This is definitely useful, and well documented (+1), though I'm not a programmer and don't really understand the code. Ideally I'd like to see an obvious example of SELinux denying an attempt to open a port, or access a path, using simple command line tools like the shell, netcat, telnet, etc. I will edit the question to make this clearer. – Thoughtitious May 01 '15 at 12:37
  • I had to look up code parts myself. I'm glad you added a bash test below. I left out Snort and postfix (maybe dovecot) errors on CentOS7 because they're packages, are more work to install, it may be fixed later and it's just more configuration. If you're already going that way it's useful for policy generation practice. – ǝɲǝɲbρɯͽ May 03 '15 at 23:01
3

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
    
Thoughtitious
  • 323
  • 1
  • 8
  • Hey yeah that works! I like specifically that you chose this "no exec content" approach, as this should definitely be caught. I've tended to prefer the auditd to prevent executable creation in the first place, but I like this too. A use case: I use a common cloud-based service that makes it hard to install new software (you have to use their package manager, and there's no sudo), but there's little point; they don't block creation or execution and they're developer environments...so I just wget/scp the packages I need and *compile* them. +1 – ǝɲǝɲbρɯͽ May 03 '15 at 22:36
1

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.

atdre
  • 111
  • 2
  • I couldn't get your second suggestion to work (using a newly created user). Also I'd rather a test that was more generic, an example of a MAC stepping up where the DAC would have allowed it: whereas this tests how well SELinux can protect against administrative changes to SELinux labeling. – Thoughtitious May 01 '15 at 12:33
0

install two small packages - no dependencies

  yum install -y vsftpd lftp

start an FTP server

  systemctl start vsftpd

create a file in root's home

  touch ~/tux.tch

move from root's home to FTP directory.
note: move, don't copy, or the fcontext of the file will change

  mv ~/tux.tch /var/ftp/pub

login to your FTP server as the FTP client user and attempt to access the new file.
note: tab auto-completion won't work here

  lftp localhost
    ls pub/tux.tch
    exit

view the denial in the raw logs

  grep AVC /var/log/audit/audit.log

or if you have setroubleshoot* installed

  grep sealert /var/log/messages