This is the fourth and final installation of a four-part series devoted to the exploration of LIDS, a Linux kernel patch that will allow users to take away the all-powerful nature of root. The first article in this series offered an overview of LIDS. The second installment looked at file restrictions, LIDS File ACLs, and LIDS enhancements of Linux capabilities. Part three discussed granting capabilities, the LIDS-specific capabilities, ACL inheritance and time-based ACLs. This segment will explore LIDS log entries, using Ptrace, some troublesome issues with LIDS and a brief discussion of what users should be using LIDS to protect.
Confounding Log Entries
Often you'll come across log entries that are hard to track down, such as the following:
LIDS: cp (3 2 inode 2728) pid 21127 user (0/0) on NULL: Try to open /var/log/ksymoops/20010419062501.ksyms for writing
Cases like this, where standard unix commands like cp, mv, and friends are causing violations are hard to track down. They are most likely being called from shell scripts, perhaps out of cron. What's even worse is that file redirection can cause similar entries:
LIDS: bash (3 2 inode 1027) pid 105 user (0/0) on tty1: Try to open /var/log/dmesg for writing,flag=33346
In this example, some shell script ran the command 'dmesg > /var/log/dmesg'. Since the redirection was done in the shell, the device and inode refer to /bin/bash itself, and almost entirely unhelpful situation.
Your job, and it's not always an easy one to do, is to track down the shell scripts that cause the violations. If the script is calling external commands (/bin/cp, etc.) then you can increase the inheritance level of the ACL to make sure those programs have the required privileges. If it's simple redirection then an additional ACL is needed. If the programs are called out of cron, then the time of the log entry will give you an indication of which programs it may be. From there, you're on your own with trial and error.
If you have a specific program that isn't working, and the system logs aren't showing you any errors, there may be other permission problems at work. For example, if the CAP_FOWNER capability is turned off (meaning that root cannot override normal Unix file permissions), then a program may not be able to read files it expects due to permission problems. This is not an ACL violation, and thus will not be reported in system logs. (You can imagine how full logs would be if a messages was generated every time a user attempted to read a file to which they didn't have access.)
In this case your best bet is to trace the process with the 'strace' command:
root# strace /path/to/program
You should then check for any system calls that fail and try to figure out where the problem is. Note that if you have disabled the CAP_SYS_PTRACE capability in lids.cap you will need to give strace this capability while you're testing:
lfs# lidsadm -A -s /usr/sbin/strace -o CAP_SYS_PTRACE -j GRANT
Make sure you turn off this ACL when you're done, of course.
There are a number of files that are troublesome for most installations. We won't go into great detail here about solutions because several options are available on the LIDS FAQ.
/etc/mtab is a file that is updated by the 'mount' and umount' commands to reflect the current state of mounted filesystems. If /etc is protected read-only, then this file cannot be updated. You can either make it writeable, or better yet replace it with a symlink to /proc/mounts, which is the kernel's up-to-date mount table. You will need to replace 'mount' with 'mount –n' in start-up scripts to avoid attempts to write to /etc/mtab.
The modules.dep file, located in /lib/modules/KERNEL_VERSION/modules.dep, is usually updated when the machine is rebooted. If you have /lib READ only (a good idea) then it cannot rewrite this file. If you haven't added or changed modules, then there's no problem. Else you should recreated this file manually with the 'depmod' command. If you installed a new kernel (as when installing LIDS for the first time, for example), the easiest way is to reboot with LIDS off (security=0) to recreate this file and any other changes that could be broken by having LIDS ACLs in effect, and then reboot into the LIDS kernel.
This file is created by init upon bootup and removed at shutdown. If we make /etc READ only, we cannot protect this file because we'd need a way to make sure it's created with the same inode each time, since LIDS ACLS are inode-dependent. You can ignore syslog messages about this, init will work just fine without /etc/initrunlvl correct.
If we make /etc READ-only, then we'll have problems with the passwd and shadow files. The programs that modify passwd and shadow like to make temporary files in /etc, and like to remove the original file and recreate, making the inode change. Yes, I'm saying that folks won't be able to change their own passwords. There are many different options available on the LIDS FAQ that you can choose from to address this problem, depending on your security requirements.
Programs That Tweak Capabilities
Some programs attempt to use or limit Linux capabilities on their own, without realizing that the admin may have already tailored the capabilities that are required. For example, the (ever-buggy) BIND DNS server attempts to limit the capabilities that it commands in order to restrict it's damage should it have a vulnerability. Say you have all capabilities removed from the bounding set, and granted 'named' the only capabilities it needs (CAP_NET_BIND_SERVICE, CAP_SETUID, CAP_SETGID, CAP_SYS_RESOURCE, and CAP_SYS_CHROOT). When 'named' attempts to remove capabilities from it's own bounding set (that it doesn't have) using the SYS_capset system call, an error will be returned, 'named' will think it failed to drop certain capabilities, and will exit with an error when, in fact, everything is fine.
In these cases you must find the occurrences where the program attempts to manipulate capabilities in the source code and remove the offending lines. For example the following line is from the 'named' source code:
if (syscall(SYS_capset, &caphead, ∩) < 0) ns_main_earlyfatal("capset failed: %s", strerror(errno));
If you simply remove these lines, 'named' will not try to modify its capabilities (which is fine, we have done that via LIDS already) and will continue running just fine - as well as BIND runs, that is.
So, What Should I Protect With LIDS?
What to protect is up to you and your paranoia. For File ACLs, I like to make /bin /boot /etc /lib /opt /root /sbin and /usr READ only at a minimum. Some things in /var, such as crontabs, are also good candidates for READ only, and of course /var/log should be set for APPEND. DENYing to /etc/shadow is fun, but requires a lot of exceptions, for example. Many folks have made their lids.sh files available, see the LIDS FAQ for pointers.
The general rule is that the more you protect as READ only, the more secure you will remain, and the more exceptions you will need to make to have a usable system.
I like to remove all capabilities from the bounding set except CAP_SYS_BOOT. In a real emergency, I like to have root able to reboot the system without making an LFS. (Especially should I forget the LIDS password and not have access to my encrypted password safe.) On a server it is not too much trouble to identify all the capabilities that are needed to have a functioning machine simply by watching the system log for violations.
All in all, my lids.sh files range from 100 - 200 lines long - with half that being comments and blank lines for readability - for a system that is fully functional as a mail, DNS, and Web server. I suggest you check the LIDS FAQ for example lids.sh scripts, which will get you jumpstarted.
Brian Hatch is an obsessive security freak and lead author of Hacking Linux Exposed and co-author of Building Linux VPNs. While he frequently stays up late to write or hack code, he thinks it's much more fun to go to the park and push his daughter in the swing as he delivers horrible puns to his fiancee.