2.6 Forgiveness Is Better than PermissionWhile I find this strategy to work well with management, it also applies to System Administration file permissions. Recognize that any file (including a directory or device file) that has any permission available to a potential cracker[15] might weaken your system's security. Linux is based on UNIX, which was developed by Bell Labs researchers before most systems were on the Internet. As such, many system files are readable by everyone and some are writable.
When I get onto someone else's system, sometimes I am surprised at how many severe file permission problems I notice. Most users were never informed about permissions and their SysAdmins never dropped a umask 027 or umask 022 into the system's or individual users' startup scripts. Why should a SysAdmin care about world-readable or world-writable files? After all, the users are trusted employees and the system is secure. Even under these circumstances there are dangers. Some user may have a weak password that gets cracked. Maybe a cracker discovered a bug in a CGI script that allows him the full access of the UID running Apache.[16] Thus, it is important to limit the damage of any breach. We looked at this in "Moving to Rings of Security" on page 26.
One common problem which occurs frequently is that there is no defined policy about who is responsible for putting said umask in startup scripts or educating the users the SysAdmin, the users themselves, or someone else. Umask commands could be put in the global startup scripts for the various shells in /etc. These include csh.login and csh.cshrc for csh and tcsh, and profile for sh and bash. It is recommended that if this is a problem at your shop, you suggest to management that you could write a draft policy for their approval. You will need to decide what is appropriate for your company's culture. 2.6.1 Directories and the Sticky BitVery few files should have world write access. Among those that should are your tmp dirs with mode 1777 (typically /tmp and either /var/tmp or /usr/tmp). As you recall, if someone has write access to a directory, Linux will allow that person to create new files in that directory, remove existing files, or move files into, out of, or within that directory. The problem that exists is that this allows a malicious user to remove someone else's temporary files from /tmp. Note that this is not as much of a problem as you might think because many programs such as vi and Mail created their temporary files in /tmp mode 600 (-rw-------) so other users cannot read or write them and keep an open file descriptor for referencing the file. Linux and UNIX have an unusual feature in that the kernel keeps track of not only the link count of the number of directory entries that point to a given inode number, but also how many open file descriptors in running programs reference it. The kernel does not free the inode or file contents until there are no more directory links to the inode, and running programs that have the file (inode) open either close it or exit. Thus, even if a malicious user removes a temporary file that your program has open, you would not lose any data or be inconvenienced. Not all programs keep their temporary files open during processing. (This technique of a program keeping its temporary files open fails over NFS because the NFS daemon will close files not accessed for a while because there is no explicit NFS close command.) Thus, a user's temporary files in the temporary directories, such as /tmp, are at risk for a malicious user removing them. The temporary files are, however, protected from being read or modified if the program that the user is using creates them mode 600. Even if the program asks for file permissions 666, truly an evil idea, the user or SysAdmin can have this corrected by specifying a umask of 027 or 022. Very few programs are so badly written that they will override umask to force more open permissions. The solution to this dilemma was to use the sticky bit, octal 1000. The graybeards out there will recall that originally, on ancient UNIX systems, the sole purpose of this sticky bit was to keep a copy of a program sticking in swap space after every user running the program finishes running it. Thus, when the next person invoked the program it did not have to be read in from the file system again. This resulted in fewer system resources being needed to start the program and less waiting time for the person invoking it. Typically a heavily used program such as the editor got its sticky bit set. In Linux (and most UNIX systems today), if a directory has the sticky bit on, the kernel will not allow someone to remove or rename files in that directory that she does not own even if the directory's write bit permissions would allow it otherwise. The point is that directories where different users each need to be able to create files but should not remove each other's files should have the sticky bit set. One of these directories, say /tmp, might have its permissions correctly set via chmod 1777 /tmp It might be time to extend this concept by enhancing the kernel so that setting a different bit prevents all but a directory's owner from creating a symbolic link in it. This will stop most "symlink attacks." 2.6.2 Finding Permission ProblemsMost of the Linux distributions carry on the proud yet inappropriate philosophy of defaulting to having much more permissive a set of file permissions than they should. Note that some of the character devices in /dev are mode 666 but this is correct for some of them. The /dev/null file throws away any data written to it so mode 666 is safe for it too. See "Stopping Access to I/O Devices" on page 268 for the details on device permissions. It is suggested that you go through your system and find unneeded permissions and then turn off the unneeded permissions. Later, in "Finding Suspicious Files" on page 645, the periodic use of find to search for files left behind by crackers is discussed. The following command will send you a mail message listing all world-writable files for bash (Bourne) shell users: find / ! -fstype proc -perm -2 ! -type l -ls 2>&1 | \ Mail -s 'world writable' your_address Csh users should use the following instead: find / ! -fstype proc -perm -2 ! -type l -ls \ |& Mail -s 'world writable' your_address The find command searches the directory trees listed (/ in this case) looking for files that match your specification. Unless parentheses or the -o operator (which means OR) is used, all expressions are ANDed together. In the ! -fstype proc clause the ! means NOT so that this clause will be true only when the portion immediately following the ! is false. The -fstype proc would be true only for files that are on a file system of type proc. In other words, ignore the pseudo files on /proc. Recall that the /proc file system does not exist on disk. Rather, it is generated dynamically by the kernel to get and set certain kernel parameters. The -perm operator is short for permissions and allows selection depending on a file's permissions. If its argument starts with a "-", it will be true for a given file if all of the permission bits specified are present. Thus, -perm -2 will be true for each file that is world-writable. This allows you to detect this potential security problem. (If the argument to -perm starts with "+", it will be true if any of the bits, instead of all of them, are true. If there is no leading - or +, -perm will be true if a file's permissions exactly match the argument.) The -ls will cause the equivalent of an ls command to be done on each matching file and is a recent feature. The -ls gives more information than the -print. Some of the later examples use -mount to cause find not to follow subdirectories on file systems other than those that the starting directories on the command line are in.
The command then pipes both standard output and standard error to the Mail command to mail the results to the system administrator's account. Becuase find can take many minutes to run on the entire file system, it is often preferable to mail the results to yourself and do something else while find runs. When I go through such a purification ritual, I will usually either redirect the output into a file such as foo or possibly pipe the output to tee and specify the output file to tee. Almost everyone who does this find is shocked at the results. Even though I try to run a tight ship, I was surprised about how many problems this find found on my laptop. This was particularly surprising because it does not have many packages installed on it because it originally had a 300 MB disk. After the find puts the suspicious file names in a file, I edit the file down to those files that actually have a problem, prepend chmod o-w to each line (with a space after the w) and then I do sh foo rm foo or csh foo rm foo This removes write permission for others from the files. As an alternative, either of the two following commands will find all world-writable files (except directories with the sticky bit on and character devices) and for each one found, will ask you if you want the world-writable bit (002) turned off. Note that they do not check the /proc file system, which is managed by the kernel. They do assume that you previously have checked your character device files in /dev because there are lots of character device files in /dev that are mode 666 (readable and writable by all or mode 622). Note that the -ok action is like -exec except that it first prompts you with the name of the command (the first argument to -ok) and the name of the file being processed and waits for you to type a line. If the line begins with y or Y, the command is executed; otherwise it is not. Rereading the find(1) manual page might prove valuable. The first form assumes that /home is a separate file system and will not check file systems other than / or /home. The second form is preferable for general use. find / /home -mount -perm -002 \( -type f \ -o -type d -o -type p -o -type b \) \ \( ! -type d -o ! -perm -1000 \) \ -ls -ok chmod o-w '{}' \; find / ! -fstype proc -perm -002 \( -type f \ -o -type d -o -type p -o -type b \) \ \( ! -type d -o ! -perm -1000 \) \ -ls -ok chmod o-w '{}' \; I suggest repeating one of the find invocations discussed in this chapter periodically, possibly monthly or weekly via cron.
Deciding which files must remain world-readable is harder than the world-writable problem because so many files should be world-readable, such as shell scripts in the bin directories, man pages, libraries, /etc/passwd and /etc/group, /etc/hosts, and /etc/resolv.conf. Certainly, on a secure system, users' files generally should not be world-readable and perhaps not even group-readable. This is where knowing your file system is useful. The following command will find all world-readable files under /home and under /usr/oracle, where there would be database-related files. This command does not check /usr/oracle/bin where Oracle-related programs are kept. It makes use of the -path option to match /usr/oracle/bin and the -prune option to skip it. It similarly ignores /home/ftp. It does not pipe standard error; you can if you desire. find /home /usr/oracle \( -path /usr/oracle/bin -o \ -path /home/ftp \) -prune -o -perm -4 -ls \ | Mail -s 'world readable' your_address You also will want to search for set-UID and set-GID programs and evaluate whether these permissions are appropriate. The following two commands will do this. Although they can be combined into one, because set-GID programs are rarer than set-UID programs, it is best to separate them. find / ! -fstype proc -perm -4000 -ls 2>&1 | \ Mail -s 'set-UID' your_address find / ! -fstype proc -perm -2000 -ls 2>&1 | \ Mail -s 'set-GID' your_address Csh users should use the following instead: find / ! -fstype proc -perm -4000 -ls \ |& Mail -s 'set-UID' your_address find / ! -fstype proc -perm -2000 -ls \ |& Mail -s 'set-GID' your_address There are many other types of suspicious files that can be found with find commands. One would be to find files with a numeric UID or GID that is not in /etc/passwd or /etc/group. These might be cracker files or files owned by users long since removed and forgotten. The following command will list these: find / ! -fstype proc '(' -nouser -o -nogroup ')' -ls The following find command will find files that are hidden from ordinary view by beginning with a ".". Expect to see .profile and similar but crackers sometimes will create a file of one of these names in other than your login directory. find / ! -fstype proc '(' -name '.??*' -o -name '.[^.]' ')' -ls The next find command will find all files owned by a specified user. It should be used after having removed an account. When I do this, I am reminded of users who have mailboxes, files in stalled print queues, etc. find / ! -fstype proc -user dbcooper -ls The following command will find files in each user's directory that they do not own and which could be the result of someone being up to no good. If ~ftp is under /home, expect files owned by root there. User collaboration might result in one user's directory having files owned by another user but this situation is rare on many systems. A similar test for group ownership may be done. csh cd /home foreach i ( * ) echo Testing $i find $i ! -user $i -ls end exit The find command is one of the most powerful and innovative features of UNIX and Linux. Often its use can solve difficult problems that have no other easy solution. 2.6.3 Using umask in Startup ScriptsRather than prodding your users and yourself to make frequent use of the ls and chmod commands, simply put an appropriate umask invocation in /etc/profile, /etc/csh.login, /etc/bashrc, /etc/zshenv, /etc/zshrc, (and possibly /etc/csh.cshrc for rsh,[17] etc.) One can use grep[18] on user accounts to check for users overriding your default umask (typically to 0) because they do not understand Linux security or do not want to be bothered.
The following command uses the curly brace expansion feature available to both csh users and to users of the default (and quite popular) bash shell. grep umask /home/*/{.profile,.bash_profile,.bashrc} grep umask /home/*/{.cshrc,.login,.tcshrc} |
Top |