General impression of RSBAC


Howtos

Howto protect sshd

Setup UM

First we need to setup RSBAC User Management modules. In /etc/nsswitch.conf we may have ‘[passwd|shadow|group]: compat rsbac’, and in /etc/pam.d/system-auth ‘[auth|account|password|session] sufficient pam_rsbac.so’ before any pam_unix.so lines. Then :

secoff$ rsbac_useradd -O && rsbac_groupadd -O
secoff$ rsbac_passwd -n secoff

Grant sshd

Sshd must be allow to change his identity during key exchange

secoff$ for user in 0 22; do
                for param in "" "-e" "-f"; do
                        auth_set_cap $param FD add /usr/sbin/sshd $user
                done
        done

Now we want sshd to be allow to change his identity only to an user who have been properly authenticated (by entering his password).

secoff$ attr_set_fd AUTH FD auth_may_setuid 3 /usr/sbin/sshd

Note: if you use CONFIG_RSBAC_AUTH_DAC_*, CONFIG_RSBAC_DAC_* you must add caps for allowed user, because they don’t use the special auth_may_setuid value : ‘Last Auth...’

secoff$ for user in 400 "1000 3000"; do
                for param in "-e" "-f"; do
                        auth_set_cap $param FD add /usr/sbin/sshd $user
                done
        done

Run sshd

Add the following parameter to sshd init script:

-o "HostbasedAuthentication no" -o "PasswordAuthentication yes" -o "ChallengeResponseAuthentication no" -o "UsePAM yes" -o "UsePrivilegeSeparation yes" -o "PermitRootLogin no"

Test

ssh secoff@your_server

If you use the unix password, then you’ll get : ‘rsbac_adf_request(): request CHANGE_OWNER, ..., prog_name sshd, prog_file /usr/sbin/sshd, uid 0, remote ip ..., target_type PROCESS, ...., attr owner, value 400, result NOT_GRANTED by AUTH’. Now you have to use the rsbac password, like that the kernel will know that secoff have been authenticate, then he’ll allow sshd to change his identity.

Conclusion

This is a pretty good security measure, because even if sshd get’s cracked, it won’t be able to gain secoff credential without his passw ord.

Howto use RES module

RES allows to enforce user limits (ulimit). Here are somes examples:

secoff$ for user in -4 root; do
attr_set_user RES $user res_max fsize 250000   # user won t create file more than 1G (block size = 4096)
attr_set_user RES $user res_max stack 100000   # user stack won t get bigger than 100 KB
attr_set_user RES $user res_max nofile 1024    # user won t open more than 1024 fds at a time
attr_set_user RES $user res_min core -1        # user will coredump by default
attr_set_user RES $user res_max nproc 200      # user won t start more than 200 process
attr_set_user RES $user res_max as 100000000   # user s process won t get bigger than 100MB
done
secoff$ attr_set_user RES root res_role 0

And that’s it !

user$ ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) 976
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
stack size              (kbytes, -s) 97
cpu time               (seconds, -t) unlimited
max user processes              (-u) 200
virtual memory          (kbytes, -v) 97656
file locks                      (-x) unlimited
user$ ulimit -u 1024
-sh: ulimit: max user processes: cannot modify limit: Operation not permitted
 
user$ for i in `seq 0 250`; do sleep 5& done
....
[195] 12759
-sh: fork: Resource temporarily unavailable

Howto protect Kernel code against tampering

Howto protect /boot device

In this example, we don’t want anyone, except secoff, to be able to update kernel in /boot.

First, let’s protect /boot directory with RC

# We create a new FD rc_type
rc_set_item TYPE `rc_get_item list_unused_fd_type_nr` type_fd_name BOOT_FD
# We allow secoff to access this type
rc_set_item ROLE 1 type_comp_fd $BOOT_FD A
# We set /boot rc_type_fd
attr_set_fd RC FD rc_type_fd $BOOT_FD /boot    
# Repeat this last one after mounting the device: When a directory get s mounted, 
#its attributes are replaced by the ones of the new device's root.

This is good, but root can still access boot data directly through /dev/sda1.

# We create a new DEV rc_type
rc_set_item TYPE `rc_get_item list_unused_dev_type_nr` type_dev_name BOOT_Device
# We allow secoff to access this type
rc_set_item ROLE 1 type_comp_dev $BOOT_Device A
# We set /dev/sda1 rc_type
attr_set_file_dir -d DEV b8:1 rc_type $BOOT_Device

Finally we wan’t secoff to be able to mount the device:

# Let s fool mount
attr_set_fd GEN FD fake_root_uid 3 /bin/mount
# And allow secoff to changes files in /boot, the GEN way:
attr_set_fd GEN FD linux_dac_disable 1 /boot    # do that when /boot is mounted !
# or the CAP way:
attr_set_user -a CAP secoff min_caps FS_MASK

Howto use RSBAC transactions

How transactions works

RSBAC transactions works pretty much the same as SQL databases transactions... It ease policies development, for example you can do without loads of NOT_GRANTED:

There are four commands to use :

To monitor what’s going on, read the ‘/proc/rsbac-info/gen_lists’ file

finally, there are two way to change attributes in a transaction, you can either

attr_set_fd -N ta_number RC FD rc_type 2 /whatever
`rsbac_list_ta -b -t 900 begin`
rsbac_menu ...
export RSBAC_TA=ta_number

User creation examples

Here is a small script which show how to use transaction for user creation purposes.

#!/bin/sh

function abord { echo -e "\n\e[1;33m*\e[1;32m $1\e[0;37m"; rsbac_list_ta -N $RSBAC_TA forget; exit 1 }
 
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
 
if [ -z "$1" ]; then echo "usage: $0 username"; exit 1; fi;
 
export RSBAC_TA="`rsbac_list_ta -t 10 begin`"
rsbac_useradd -x 60 -w 30 -g users -p '' $1 || myabord "Could not create user"
rsbac_usermod -l 0 $1 || myabord "Could not usermod"
 
attr_set_user RC $1 rc_def_role `rc_get_item list_roles | grep ' Remote_Users$' | awk '{print $1}'` || myabord "Could not set def role"
attr_set_user CAP $1 min_caps IPC_LOCK || myabord "attr_set_user"
attr_set_user CAP $1 cap_ld_env 1 || myabord "attr_set_user"
 
rsbac_list_ta -N $RSBAC_TA commit || myabord "rsbac_list_ta"
 
mkdir -m 700 /home/$1
chown $1 /home/$1

Howto use network template

How networks templates works

First some documentation. For each network access, the adf will try to match the object with a network template from lowest to highest ordering number until it matches one. So general purpose templates should have high numbers, and more detailed templates should have low numbers.

Web server example

Let’s try to enforce network access of a web server First, we create network template, with rsbac_nettemp_def_menu, and for each template we create a new rc_netobj_type with the name + _NETOBJ

Name Nr Family Type Address Protocol Ports
DNS_SRV 53 INET DGRAM nameserver/32 UDP 53:53
TCP 300000 INET STREAM 0.0.0.0/0 TCP
UDP 300001 INET DGRAM 0.0.0.0/0 UDP
NETLINK 300002 NETLINK RAW ANY
HTTPS 200443 INET STREAM 0.0.0.0/0 TCP 443:443
LAN_TCP 100000 INET STREAM 192.168.0.0/16 TCP


The NETLINK socket is a special socket family for asking network configuration to the kernel. So first, we must allow apache to access this template.

Then apache will create a TCP socket. At this point the netobj is defined as follow : ‘INET STREAM proto TCP local 0.0.0.0:0 remote 0.0.0.0:0’. So the TCP template will match.

Then apache will bind this socket. The netobj is defined as follow: ‘INET STREAM proto TCP local 0.0.0.0:443 remote 0.0.0.0:0, attr sock_type, value STREAM’, aka HTTPS

Finally, when a browser connects to the server, the netobj is defined as follow : ‘INET STREAM proto TCP local eth0:SRV_ADDR:443 remote CLIENT_ADDR:35967’ aka LAN_TCP

So here is the list of necessary type_comp apache needs to be available for lan clients:

Netobj Access
NETLINK_NETOBJ CREATE GET_STATUS_DATA BIND RECEIVE SEND
TCP_NETOBJ CREATE GET_STATUS_DATA MODIFY_SYSTEM_DATA
HTTPS_NETOBJ BIND LISTEN MODIFY_SYSTEM_DATA NET_SHUTDOWN
LAN_TCP ACCEPT GET_STATUS_DATA READ RECEIVE WRITE SEND NET_SHUTDOWN
UDP_NETOBJ CREATE GET_STATUS_DATA MODIFY_SYSTEM_DATA IOCTL NET_SHUTDOWN
DNS_SRV_NETOBJ CONNECT SEND RECEIVE


And here you go !