Securing your system with Linux Intrusion Detection System

Closing the Lid


If you're ready for mandatory access control and you're looking for an alternative to SELinux and AppArmor, try locking down your system with Linux Intrusion Detection System.

By James Mohr

Bratscher, photocase.com

Conventional Linux security gives an all-powerful user access to the entire system. The Linux root user has the power to do anything and everything. This design has led to a number of issues. For instance, an intruder who gains the root password or forces a root-level application to crash can quickly get control of the whole system. Also, many threats come from within, and managers often worry about who is watching the watchers. In these environments, it makes sense to limit the privileges of the root user.

Developers have rolled out several solutions over the years that supplement the conventional Unix discretionary access controls with a system of mandatory access control. Mandatory access control systems such as SELinux [1] and AppArmor [2] provide several benefits, including the chance to limit the activities of root.

Another security solution offering mandatory access control for Linux is the Linux Intrusion Detection System (LIDS) [3]. LIDS has been around for several years, and the developers continue to update it for new kernel versions (although the documentation is due for an upgrade). The latest version supports Linux kernel 2.6.28.

LIDS is a kernel patch, along with a couple of utilities, that implements a number of security features. When implemented correctly, LIDS can dramatically increase your system's security.

Under the LID

Like other mandatory access control systems, LIDS goes beyond the simple user/group/other permissions to support much finer control over who can access a particular file or directory and what they can do with it. For example, you can give access to a directory to someone who is neither the owner nor a member of the group. Access to an object is defined through an Access Control List (ACL). Several Linux tools implement various forms of ACLs. In addition to protecting files and directories, LIDS applies a kind of ACL-based access control to processes. For example, you can prevent a process from changing permissions on a file, even if it normally has that right. LIDS implements a system of capabilities that controls a user's access to process-related privileges (see Table 1). If a capability is disabled, it does not matter what rights the file permissions and ownership would normally allow it - LIDS will stop you from carrying out the task.

The LIDS ACLs are integrated into the Virtual File System (VFS) layer, so you can use them on any filesystem, regardless of whether the system supports ACLs natively or not. LIDS ACLs are not stored on the actual filesystem but in files in the /etc/lids directory. You can even configure the system to access ACLs on remotely mounted filesystems using Samba or NFS.

LIDS offers a number of other security benefits, including:

The security enhancements provided with LIDS will help you keep intruders away, however, you should be aware of the extent to which LIDS restricts access and be prepared for any disruption to your environment. For instance, one of the key benefits of LIDS is preventing the execution of untrusted code. If you are working in a development environment in which you are constantly compiling different programs, the compiled programs might not run correctly when LIDS restricts their access.

Getting and Installing LIDS

LIDS is a Linux kernel patch that you need to compile and install on your system. In that it is a kernel patch, each version of LIDS applies to a specific kernel version, So when you download the source code [3], make sure you have the version for your specific kernel.

Notes in several places exhort you to compile LIDS using the source code for a specific distribution. Possibly the developers of the distribution you are using made changes to the kernel source so the patch doesn't work correctly. The solution is to download the source code for a fresh, "vanilla" kernel and compiled that.

Installing LIDS on a production machine is potentially dangerous. Anytime you tinker with the kernel, problems can occur, so you need to follow normal safety precautions to ensure you can boot from previous kernels. If the kernel boots properly, but you have other problems, turn off LIDS at boot time by adding lids=0 to the boot string.

To get a working LIDS system without installing the patch and rebooting, download one of the VMware images [4]. These images even work with free VMware versions.

I downloaded and compiled using a 2.6.28 kernel. In addition to my new compiled kernel version, I worked with a CentOS version running a 2.6.9 Kernel with lids-2.2.2, which I downloaded as a VMware image. For details of the various compile options, I point you to the documentation provided with the LIDS source code. Implementing the patch and making any changes to your existing kernel configuration is documented well enough that I won't go into the details here. Some LIDS features need to be enabled when the kernel is compiled: otherwise, they will not be available. See the documentation that comes with the source code for more details.

Basic LIDS Configuration

The /etc/lids directory contains the LIDS configuration files. Note that, once LIDS is running, this directory is inaccessible to all users, including root. Several configuration files reside in this directory, some of which apply only to specific LIDS states. See the box titled "Primary LIDS Configuration Files."

Primary LIDS Configuration Files
01 /etc/lids/lids.ini          Initial LIDS values.
02 /etc/lids/lids.cap          LIDS capability bounding set.
03 /etc/lids/lids.conf         LIDS ACL configuration file.
04 /etc/lids/lids.pw           LIDS password (used to create a LIDS Free Session).
05 /etc/lids/lids.net          LIDS network notification configuration.
06 /etc/lids/lids.conf.sh      Shell script that sets up various aspects of LIDS

The .cap files contain the capability definitions. The .conf files are files that describe the ACL configuration. If a configuration file references a particular state (i.e., boot), it applies only to that state.

Using the lids.net file, you can configure LIDS to send alerts when specific security-related events occur on the network. I was not able to find any method of sending a notification other than email, nor could I find any apparent way of defining the events for which a message is sent. However, this problem is not too hard to overcome because the access violations are written to syslogd and thus to the messages file. You could configure a log parser to read the log and send a message with the use of another notification mechanism (e.g., you could send it to Nagios).

Running LIDS

When LIDS is running, it can occupy one of three states. As its name implies, the BOOT state is when the system is booting up and initializing. This state also includes startup for system services (daemons). The POSTBOOT state is after the system has booted and it is running "normally." Finally, the SHUTDOWN state is when the machine is shutting down. Each of the states has its own configuration files located in /etc/lids.

The different states are necessary because you likely want system services to access different files and directories during startup and shutdown. PID (Process Identification) files, for example, must be written when the system starts up; however, it might be considered a security violation to write these files during normal operations. Therefore, PID files are only accessible in the BOOT state. (Note that you can also run a LIDS Free Session at any time to write these files.)

The BOOT state occurs naturally while the system is booting, and you have no reason to go specifically into this state. The POSTBOOT state, which represents the normal operating mode, is reached by sealing the kernel. To switch to the SHUTDOWN state manually, you can enter the following command line:

lidsadm -S -- +SHUTDOWN

LIDS is not really running until the kernel is sealed. By default, the kernel is not sealed automatically. You can seal the kernel with an init script that is configured to run as the last script. In one of the virtual machines, you can download the init script zzz-bootup-end, which is started as S99zzz-bootup-end - so it more than likely ends up running last. This small script simply runs:

lidsadm -I +TPE

The -I option initializes LIDS (sealing the kernel), and the +TPE activates TPE mode.

The lidsadm command is the primary administrative tool, and it is useful simply to think of it as managing LIDS as a whole. In older versions of LIDS, lidsadmin contained all of the administrative and configuration functions, including setting or clearing ACLs, sealing the kernel, or turning off LIDS entirely. In newer versions, certain functions have been redefined as "configuration," and these functions are included in the new lidsconf command. As its name implies, lidsconf (Figure 1) is used to configure LIDS. For details on the various options for each of the programs, take a look at the appropriate man page.

Figure 1: Checking access settings with lidsconf.

The changes made by LIDS are swift and all-encompassing. Once you activate the LIDS kernel module, you will quickly discover that even some of the more basic functions are no longer possible. For example, you might not even be able to stop the CUPS printer service because even root does not have permission. This result is entirely consistent with the philosophy of ACLs - if you do not have access to the appropriate files and directories, you won't be able to delete a PID file when a service is stopped. Of course, you can change this configuration, but in any case, make sure you're prepared before you throw the switch.

Another common use of the lidsadm command is to create a LIDS Free Session (LFS). Creating an LFS is necessary when you need to make changes to LIDS itself once it is running. To create an LFS, enter the following command:

lidsadm -S -- -LIDS

To re-enable LIDS in the current sessions, change the option to +LIDS. Note that this command will result in a prompt for the LIDS password, which you set during the installation.

For files and directories that must be protected in all states, you can use GLOBAL ACL, although it is also possible to define a global ACL and still have it overridden in a specific state. Overriding a general configuration with a more specific configuration is a basic principle of LIDS.

Setting up ACLs

The LIDS ACLs are supplemental to any permissions the base operating system applies. This includes standard Unix permissions, as well as any ACLs the respective filesystem provides. The layers of overlapping ACLs can be confusing if you're accustomed to the simplicity of traditional Unix permissions.

LIDS ACLs support several different types of permissions. DENY is absolute, meaning that nothing can even see the object. READ means the object is read-only and cannot be modified. APPEND lets you add to files, but you cannot change them otherwise. This option is useful for logfiles that are regularly written to without the need for later modification. If you are given WRITE access to an object, which allows you to make changes, the object is more or less unprotected.

It is important to note that when an ACL is applied to a directory, the permissions are recursive. This means that if you want to protect an entire directory, you do not need to mention every file, just the parent directory. However, you can define an ACL for a specific file that would then overwrite the general ACL for the directory.

ACL restrictions consist of a subject, which is a program, library, or module, and an object, which is a file or capability to which the ACL applies. As mentioned before, lidsconf is used to configure ACLs. The basic syntax is as follows:

lidsconf -A acl_type -s subject -o object -j action

The acl_type is any one of the three states or the (default) option GLOBAL, which is then valid for all states. An action is one of the permissions types discussed above.

If you want to configure all files in the /var/log directory so that they can only be written to, you could run the following command:

lidsconf -A -o /var/log -j APPEND

In this example, because the acl_type is blank, it defaults to GLOBAL. The object is the /var/log directory, and I have set APPEND permissions. Because I did not specify a subject (a program), LIDS will default to all programs, libraries, and modules unless a limitation is specifically defined elsewhere.

The option of imposing ACLs on a directory that affects the files underneath (and can be overridden by more specific ACLs) is useful in many cases. For example, you could define a directory to be invisible (i.e., DENY) but allow access to a specific number of files. To override the APPEND privilege with WRITE for a specific program, the command might look like this:

lidsconf -A -s /usr/local/bin/myprogam -o /var/log/ -j WRITE

Explicitly listing the subject (/usr/local/bin/myprogram) ensures that no other program can write to the /var/log directory to move or rename files. In this case, the general ACL would say that nothing could write to the directory, but the more specific ACL would allow writing only for the program specified as the subject. Another common example is to deny all programs access to /etc/shadow, so that not even root can see the encrypted password but allow access for specific programs such as login or sshd.

Also, it is important to keep in mind that security is not just about file permissions, but about the programs doing the accessing as well. If the accessing program is insecure, then all bets are off. To ensure the security of the entire system, LIDS insists that accessing programs (i.e., the subjects) be protected as well. For example, I could not grant access to the login program unless it is protected by an ACL itself. (Note that /bin/login is already protected by default.)

Permissions and Capabilities

One feature that sets LIDS apart from traditional ACLs is that an object does not need to be a file or directory. Instead, it can be a capability, such as the ability to bind to a specific port (CAP_NET_BIND_SERVICE). Without this capability, network services could not bind to their respective ports. For capabilities (as apposed to files and directories), LIDS provides two additional permission types: GRANT and DISABLE. As the name implies, GRANT gives the capability to the specific subject.

Assuming you have a web server on your system, the command for granting a certain capability to the web server program might look like this:

lidsconf -A -s /usr/sbin/httpd2 -o CAP_NET_BIND_SERVICE 80 -j GRANT

In the preceding command, note that the port number (80) follows the capability. This requirement limits the httpd2 binary to only port 80. Therefore, it would be impossible to run httpd2 on any other port or let any other binary bind to port 80. On many systems, what is actually started is a symbolic link. Because LIDS is based on inode, the program that actually runs (e.g., httpd2-prefork) might not run because it was not granted the necessary capability.

Inode

The LIDS ACLs are based on the inode of the file, which you can see in the respective .conf file. Internally, LIDS stores the list of protected files on the basis of the filesystem and inode. The advantage here is that the hard links to files are automatically protected, without the need to set each one individually. The disadvantage is that when a file is first moved and then replaced with a newer version, you need to update the inode list with

lidsconf -U

to update the configuration files, and then

lidsadm -S -- +RELOAD_CONF

to reload the current configuration into the kernel.

Finding Out More

As of this writing, the LIDS project is in a state of transition. Updates to the project website are fairly infrequent. However, the most recent file on the LIDS homepage [1] is relatively recent (January 2009). The latest LIDS version is 2.2.3rc7, which is for kernel 2.6.28.

LIDS documentation is relatively old. The FAQ is one of the more recent documents, and it is dated May 19th, 2003. I didn't encounter anything technical that appeared incorrect, with the exception that some documents indicate that lidsadm still performs the configuration, and a few links were dead. A few of the documents refer to a LIDS wiki, but as of this writing, the hostname is not resolved by DNS. The LIDS homepage includes links to several documents that are only in Japanese.

SourceForge lets you subscribe to a LIDS mailing list; however, since I started subscribing, I have gotten nothing but spam. A low-traffic forum is available from the LIDS homepage, but responses can take a week or longer.

The current state of the help sources means that, although the developers continue to update the LDS module, you are sometimes on your own if you run into trouble, which means you should make room for some trial and error. I suggest using one of the VMware images to become familiar with LIDS before you install it on a production machine.

INFO
[1] SELinux: http://fedoraproject.org/wiki/SELinux
[2] AppArmor: http://www.opensuse.org/AppArmor
[3] LIDS homepage: www.lids.org
[4] Downloadable VMware images: http://www.lids.jp/vmware.download.html