Пропускане към основното съдържание

Anatomy of Security-(SELinux)

Introduction: Public networks like the Internet are dangerous places. Anyone who has a computer attached to the Internet (even transiently) understands these dangers. Attackers can exploit insecurities to gain access to a system, to obtain unauthorized access to information, or to repurpose a computer in order to send spam or participate in attacks on other high-profile systems (using SYN floods, as part of a Distributed Denial of Service attacks). Distributed Denial of Service (DDoS) attacks are orchestrated from many systems across the Internet (so-called zombie computers) to consume resources on the target system and make it unusable for legitimate users (exploiting TCP's three-way handshake). For more information on a protocol that removes this ability by using a four-way handshake with cookies (Stream Control Transmission Protocol [SCTP]), see the Resources section. The origin of SELinux SELinux is a product of government and industry, with design and development provided by the NSA, Network Associates, Tresys, and many others. Although it was introduced by the NSA as a set of patches, it's mainlined into the Linux kernel as of 2.6. GNU/Linux is very secure, but it's also very dynamic: changes can appear that open holes into the operating system that can then be exploited. Although considerable attention is paid to preventing unauthorized access, what happens after an entry has occurred? This article explores the ideas behind SELinux and its basic architecture. A complete overview of SELinux could be the topic of an entire book (see the Resources section), so this article sticks to the basics to give you an idea of why SELinux is important and how it's implemented. Access control methods Most operating systems use access controls to determine whether an entity (user or program) can access a given resource. UNIX®-based systems use a form of discretionary access control (DAC). This method restricts access to objects based commonly on the groups to which they belong. For examples, files in GNU/Linux have an owner, a group, and a set of permissions. The permissions define who can access a given file, who can read it, who can write to it, and who can execute it. These permissions are split into three sets of users, representing the user (owner of the file), the group (all users who are members of a group), and others (all users who are neither members of the group nor owner of the file). Lumping access controls like this creates a problem because an exploited program inherits the access controls of the user. Thus the program can do things at the user's access level, which is undesirable. Rather than define restrictions this way, it's more secure to use the principle of least privilege: programs can do what they need to perform their task, but nothing more. For example, if you have a program that responds to socket requests but doesn't need to access the file system, then that program should be able to listen on a given socket but not have access to the file system. That way, if the program is exploited in some way, its access is explicitly minimized. This type of control is called mandatory access control (MAC). Another approach to controlling access is role-based access control (RBAC). In RBAC, permissions are provided based on roles that are granted by the security system. The concept of a role differs from that of a traditional group in that a group represents one or more users. A role can represent multiple users, but it also represents the permissions that a set of users can perform. SELinux adds both MAC and RBAC to the GNU/Linux operating system. The next section explores the SELinux implementation and how security enforcement was transparently added to the Linux kernel.

Linux security implementation
In the early days of SELinux, while it was still a set of patches, it provided its own security framework. This was problematic because it locked GNU/Linux into a single access-control architecture. Instead of adopting a single approach, the Linux kernel inherited a generic framework that separated policy from enforcement. This solution was the Linux Security Module (LSM) framework. The LSM provides a general-purpose framework for security that allows security models to be implemented as loadable kernel modules (see Figure 1). Figure 1. Security policy and enforcement are independent using SELinux.
Kernel code is modified prior to accessing internal objects to invoke a hook that represents an enforcement function, which implements the security policy. This function validates that the operation may proceed based on the predefined policies. The security functions are stored in a security operations structure that covers the fundamental operations that must be protected. For example, the security_socket_create hook (security_ops->socket_create) checks permissions prior to creating a new socket and considers the protocol family, the type, the protocol, and whether the socket is created within the kernel or in user-space. Listing 1 provides a sample of the code from the socket.c for socket creation (see ./linux/net/socket.c).

Listing 1. Kernel code for socket creation
 static int __sock_create(int family, int type, int protocol,   
              struct socket **res, int kern)  
     int err;  
     struct socket *sock;  
      *   Check protocol is in range  
     if (family < 0 || family >= NPROTO)  
         return -EAFNOSUPPORT;  
     if (type < 0 || type >= SOCK_MAX)  
         return -EINVAL;  
     err = security_socket_create(family, type, protocol, kern);  
     if (err)  
         return err;  

The function security_socket_create is defined in ./linux/include/linux/security.h. It provides indirection from the call security_socket_create to the function that's dynamically installed in the security_ops structure (see Listing 2). Listing 2. Indirect call for the socket-creation check

 static inline int security_socket_create (int family, int type,  
                      int protocol, int kern)  
     return security_ops->socket_create(family, type, protocol, kern);  

The function in the security_ops structure is installed by the security module. In this case, the hooks are defined in the loadable kernel module for SELinux. Each SELinux call is defined within the hooks file that completes the indirection from the kernel function to the dynamic call for the particular security module (see Listing 3 from .../linux/security/selinux/hooks.c).
Listing 3. The SELinux socket-creation check
 static int selinux_socket_create(int family, int type,  
                  int protocol, int kern)  
     int err = 0;  
     struct task_security_struct *tsec;  
     if (kern)  
         goto out;  
     tsec = current->security;  
     err = avc_has_perm(tsec->sid, tsec->sid,  
               socket_type_to_security_class(family, type,  
               protocol), SOCKET__CREATE, NULL);  
     return err;  

At the core of Listing 3 is the call to validate that the current operation is permitted for current task (as defined by current->security, where current represents the currently executing task). The Access Vector Cache (AVC) is a cache of previous SELinux decisions (to increase the process's performance). This call includes the source security identifier (sid), the security class (constructed from the details of the requested operation), the particular socket call, and optional auxiliary audit data. If the decision isn't found in the cache, then the security server is invoked to obtain the decision (this process is shown in Figure 2). Figure 2. Layered Linux security process

The callback hooks initialized into security_ops are defined dynamically as a loadable kernel module (through register_security()) but otherwise contain dummy stub functions in the event that no security module is loaded (see ./linux/security/dummy.c). These stub functions implement the standard Linux DAC policy. The callback hooks exist at all points where object mediation must be provided for security. These include task management (creation, signaling, waiting), program loading (execve), file system management (superblock, inode, and filehooks), IPC (message queues, shared memory, and semaphore operations), module hooks (insertion and removal), and network hooks (covering sockets, netlink, network devices, and other protocol interfaces). You can learn more about the various hooks in the Resources section or by reviewing the security.h file. Managing the policies for SELinux is well beyond the scope of this article, but you can find more information about SELinux configuration in the Resources section.


Temporarily switch off enforcement You can switch the system into permissive mode with the following command:
 echo 0 >/selinux/enforce  

You'll need to be logged in as root, and in the sysadm_r role:
 newrole -r sysadm_r  

To switch back into enforcing mode:
 echo 1 >/selinux/enforce  

In Fedora Core and RedHat Enterprise Linux you can use the
command with a 0 or 1 option to set permissive or enforcing mode, its just a slightly easier command than the above. To check what mode the system is in,
 cat /selinux/enforce  

which will print a "0" or "1" for permissive or enforcing - probably printed at the beginning of the line of the command prompt. Permanently Permissive The above will switch off enforcement temporarily - until you reboot the system. If you want the system to always start in permissive mode, then here is how you do it. In Fedora Core and RedHat Enterprise, edit /etc/selinux/config and you will see some lines like this:
 # This file controls the state of SELinux on the system.  
 # SELINUX= can take one of these three values:  
 # enforcing - SELinux security policy is enforced.  
 # permissive - SELinux prints warnings instead of enforcing.  
 # disabled - No SELinux policy is loaded.  
 # SELINUXTYPE= can take one of these two values:  
 # targeted - Only targeted network daemons are protected.  
 # strict - Full SELinux protection.  

... just change SELINUX=enforcing to SELINUX=permissive, and you're done. Reboot if you want to prove it. For the other Linuxes which don't have the /etc/selinux/config file, you just need to edit the kernel boot line, usually in /boot/grub/grub.conf if you're using the GRUB boot loader. On the kernel line, add enforcing=0 at the end. For example,
 title SE-Linux Test System  
      root (hd0,0)  
      kernel /boot/vmlinuz-2.4.20-selinux-2003040709 ro root=/dev/hda1 nousb enforcing=0  
      #initrd /boot/initrd-2.4.20-selinux-2003040709.img  

Fully Disabling SELinux Fully disabling SELinux goes one step further than just switching into permissive mode. Disabling will completely disable all SELinux functions including file and process labelling. In Fedora Core and RedHat Enterprise, edit /etc/selinux/config and change the SELINUX line to SELINUX=disabled:
 # This file controls the state of SELinux on the system.  
 # SELINUX= can take one of these three values:  
 # enforcing - SELinux security policy is enforced.  
 # permissive - SELinux prints warnings instead of enforcing.  
 # disabled - No SELinux policy is loaded.  
 # SELINUXTYPE= can take one of these two values:  
 # targeted - Only targeted network daemons are protected.  
 # strict - Full SELinux protection.  

... and then reboot the system. For the other Linuxes which don't have the /etc/selinux/config file, you just need to edit the kernel boot line, usually in /boot/grub/grub.conf, if you're using the GRUB boot loader. On the kernel line, add selinux=0 at the end. For example,
 title SE-Linux Test System  
     root (hd0,0)  
     kernel /boot/vmlinuz-2.4.20-selinux-2003040709 ro root=/dev/hda1 nousb selinux=0  
     #initrd /boot/initrd-2.4.20-selinux-2003040709.img  

You will have to reboot to disable SELinux, you just can't do it while the system is running. Re-Enabling SELinux If you've disabled SELinux as in the section above, and you want to enable it again then you've got a bit of work to do. The problem will be that files created or changed when SELinux was disabled won't have the correct file labels on them - if you just reboot in enforcing mode then a lot of stuff won't work properly. What you need to do is to enable SELinux by editing /etc/selinux/config (for Fedora/RedHat) or by adding selinux=1 to the kernel boot line, then boot into permissive mode, then relabel everything, and then reboot into (or simply switch to) enforcing mode. After booting into permissive mode, run
 fixfiles relabel  

Alternatively, in Fedora and RedHat Enterprise Linux you can run
 touch /.autorelabel  

and reboot or put

on the boot command line - in both cases the file system gets a full relabel early in the boot process. Note that this can take quite some time for systems with a large number of files. After relabelling the filesystem, you can switch to enforcing mode (see above) and your system should be fully enforcing again.


Популярни публикации от този блог

DVWA - Brute Force (High Level) - Anti-CSRF Tokens

This is the final "how to" guide which brute focuses Damn Vulnerable Web Application (DVWA), this time on the high security level. It is an expansion from the "low" level (which is a straightforward HTTP GET form attack). The main login screen shares similar issues (brute force-able and with anti-CSRF tokens). The only other posting is the "medium" security level post (which deals with timing issues).

For the final time, let's pretend we do not know any credentials for DVWA.... Let's play dumb and brute force DVWA... once and for all!
TL;DR: Quick copy/paste
1: CSRF=$(curl -s -c dvwa.cookie "" | awk -F 'value=' '/user_token/ {print $2}' | cut -d "'" -f2) 2: SESSIONID=$(grep PHPSESSID dvwa.cookie | cut -d $'\t' -f7) 3: curl -s -b dvwa.cookie -d "username=admin&password=password&user_token=${CSRF}&Login=Login" "…

List of TCP and UDP port numbers

This is a list of Internet socket port numbers used by protocols of the transport layer of the Internet Protocol Suite for the establishment of host-to-host connectivity. Originally, port numbers were used by the Network Control Program (NCP) in the ARPANET for which two ports were required for half-duplex transmission. Later, the Transmission Control Protocol (TCP) and the User Datagram Protocol (UDP) needed only one port for full-duplex, bidirectional traffic. The even-numbered ports were not used, and this resulted in some even numbers in the well-known port number range being unassigned. The Stream Control Transmission Protocol (SCTP) and the Datagram Congestion Control Protocol (DCCP) also use port numbers. They usually use port numbers that match the services of the corresponding TCP or UDP implementation, if they exist. The Internet Assigned Numbers Authority (IANA) is responsible for maintaining the official assignments of port numbers for specific uses. However, many unoff…