UNIX Security Risks You've chosen your UNIX distribution (or someone else did it for you), and you need to know where the risks are. All operating systems have security problems no matter what anyone might tell you to the contrary. Anything with some complexity, written by humans and managed by humans, inherits the wonderful flaws of the authors along the way. The main risk areas on a typical, modern day UNIX system tend to be Misconfigured/buggy network daemons. These leave your system open to attack from anyone who can "see" your server across the network. The attacker doesn't need an account on your system to exploit these security holes. These are classified as remote vulnerabilities. Poorly chosen user passwords. Bottom line: Passwords are an inconvenience for most users. Systems configured to enforce fascist password rules only encourage users to write down their passwords. A middle ground is required this is a people issue, rather than a technical one. Buggy privileged programs (set-uid/set-gid). What happens when an attacker subverts a program that executes with special privileges? Well, it depends on the specific vulnerability. All too often, though, system security is breached, and the attacker can take control over the operating system. These problems are classified as local vulnerabilities, as the attacker requires a user account to exploit them (which might or might not be obtained legitimately). Filesystem nightmares. Badly set file permissions, sloppy handling of temporary files, race conditions, and insecure defaults are all culprits. Exploiting these can lead to leakage of sensitive information, introduction of Trojan code, and destruction of data. Bottom line: An insecure filesystem affects the integrity of the entire system. Insecure applications. N ive designs and sloppy programming practices combine to produce a giant sore on your system exposed to anyone who tries to exploit the myriad of possible weaknesses. Bolting down your UNIX server is not enough, if someone can drive a tank through your application security. The common trait of these risk areas is insecurely written code. We'll cover each category in more detail in the following sections. Buzzt! Actually, some people use these weaknesses to study attackers. Lance Spitzner used to get his kicks from blowing up things in his tanks. Today, he enjoys observing attacks launched against his honey pot system: http://project.honeypot.org/ A sacrificial host is built running a default Red Hat Linux install with no security patches and connected to the Internet (typically outside a firewall or within a DMZ). A series of logging mechanisms are activated to record probes and attacks. After a compromise, Lance is able to reconstruct all the attackers'activity via the captured packet trace. This kind of exercise provides an insight into the way attackers compromise a victim machine and, more importantly, what they do when they have. A number of organizations run honey pots to identify new attacks "in the wild." By coordinating their efforts, they are able to track new trends and issue alerts to the wider community. Be warned though: Having drawn attackers to your site, you had better be sure they won't compromise your real network or discover you monitoring their activity. Sophisticated attackers can identify a honey pot very quickly. | User Accounts If you haven't read Chapter 14, "Password Crackers," I recommend that you do so now. Users, bless 'em, can give up your system's security no matter what lockdown procedures you have implemented. The age-old problem of poorly chosen passwords continues to plague any operating system or device that requires them. One security practitioner I know describes passwords as "past their sell-by date." The problem doesn't seem to go away, and there is no reason to believe that it is going to. Therefore, a change of tack might be necessary, and you should give serious consideration to either moving to other forms of authentication such as one-time passwords (OTP), biometrics, or smartcards. No authentication system is perfect many appear impressive until you start analyzing their issues. However, it doesn't take a giant leap to improve upon passwords. Assuming you're stuck with UNIX passwords, here's what can you can do to improve things: Limit access to the root account on a need-to-have basis. Root is all powerful, and you'll want to avoid giving this level of access to anyone who doesn't have a legitimate need for it. Don't give root access to anyone who can't demonstrate adequate technical expertise AND judgment. You get to define "adequate." Mistakes will happen from time to time, but allowing untrained newbies access to root is asking for trouble. At the same time though, don't make a big thing about the root account to those you refuse it might cause resentment that could lead to other security problems! Set a strong password on the root account. Stick to a minimum of eight characters and include special characters. Disable root logins across the network. Have admins make use of su, or, better yet, deploy sudo. Note Sudo is an incredibly useful utility. It allows the administrator to permit users to run commands for which they do not usually have the privilege. For example, you have a helpdesk that needs to be able to change passwords for everybody except the administrators. This is easy with sudo. You define a sudo rule to permit anyone in the helpdesk group (or using the helpdesk user id, if you are not allergic to shared accounts) to run the passwd command as root with a twist. You also define what arguments can or cannot be passed to the command. So, in this case, you would specify the administrator user ids as invalid arguments (by using the exclamation mark to signify negation). Sudo can be found here: http://www.courtesan.com/sudo/. Store the root password offline in an envelope (signed across the join) in a secure place. In large environments, make sure that a log of access is kept. Don't use the same passwords across all machines. The compromise of a single password should not result in a complete giveaway. Categorize your systems in virtual groups, by either risk or data sensitivity. Assign a unique root password to each virtual group. In practice, these groups can be test, development, and production. However, if you're storing the same data on all those systems, you either need to revisit your data security policy or think of another way to group your systems. Ban access to remote access servers that don't support encryption. Telnet and FTP send passwords in cleartext across the network. At a minimum, make sure your privileged users use ssh and scp. Implement password construction checks on the server. Set minimum values for password length, the number of alphanumerics, and, where supported, special characters. Implement real-time password dictionary checks. Use software like npasswd (http://www.utexas.edu/cc/unix/software/npasswd/)as a replacement for the stock password program. This type of software does require some configuration on the part of the administrator but goes a long way toward solving the problem of easy-to-guess passwords being used. Instigate a password-cracking policy. Every month or quarter, attempt to crack all passwords (administrator accounts included). Track the percentage cracked and set targets. Use a decent-sized cracking dictionary and add words that relate to your environment (for example, project names, team names, supplier names, nicknames, and so on). Create a password policy that states the required length and composition of passwords. Make sure all system users have seen it. Educate your users on strategies for choosing good passwords. For example, have them think of a line from a favorite song or quote and select the first letter of each word to make up a password for example, "I Left My Heart in San Francisco" would be IlmhiSF. Then mutate the password by adding in special characters for example, !lmhi$F_. That would take a while to crack. This can make hard passwords easy to remember. Don't think that by replacing letters with numbers in passwords you are going to outsmart a cracker. Password cracking programs do this automatically, too. Give serious consideration to enforcing account lockout after three or five failed logins. This can lead to a denial of service attack if you are in a hostile environment a malicious user could lock out all the accounts on purpose simply by typing gibberish for users'passwords. (However, DoS is generally a low risk in an internal network.) Make sure that your helpdesk doesn't just re-enable locked accounts (or create new ones) for anyone who calls the desk with a friendly voice. It's a well-known fact that social engineering of over-obliging support staff is easier than bypassing a well-configured firewall. Don't let your support staff fall into the trap of using the same password when resetting locked accounts. Invest in some software that generates passwords that are phonetically easy to pronounce. (This won't work for multilingual support desks.) Mail the author if you find a good product. If a user calls to have his password reset, use a callback scheme on a prearranged number or, failing that, leave the new password on the user's voicemail. Don't tell the user the password there and then unless you know the person's voice well enough to spot an impersonator. This might sound a little too paranoid. However, consider what someone might gain by doing this and how stupid you'd look if you simply gave the password to them on a plate! Go on walkabout every now and then to check whether users are writing passwords down. For example, are passwords written on sticky notes on monitors? If they are, have a quiet word with the user. Persistent offenders might find remembering different passwords to different machines hard. Consider using software like Counterpane's Password Safe (http://www.counterpane.com/passsafe.html). This installs on the client machine and can securely store passwords unlocked via a single password. Just make sure this one is strong and not written down! This software is particularly useful for administrators. Make sure that your systems are using shadow passwords. It used to be that UNIX stored passwords in the /etc/passwd file. However, as CPU technology forged ahead, it wasn't long before these passwords were being cracked. Check to make sure that your passwords are being stored in a file readable only by root. Avoid hard-coding passwords in scripts if at all possible. If you have to, then make sure file permissions are set to user access only. Avoid badly written client software that stores UNIX server passwords on the client in an easy to decrypt/decipher form. XOR'd in the NT registry does this, for example. Filesystem Security This section reviews fundamental filesystem and privilege concepts. When it comes to input and output, UNIX treats everything as a file. In fact, the term file has multiple meanings in UNIX it can be a Regular file. A sequence of data bytes collectively regarded by the operating system as a file. Directory file. A list of filenames and pointers to file meta information (that's a fancy way for saying "information about a file"). If you have read access to a directory, it means you can read the contents of the directory in other words, get a directory listing (a la ls(1)). However, only the UNIX kernel has the capability to modify the contents of this file (for example, insert a new entry). Symbolic link. Contains the name of another file. When a symbolic link is accessed, the kernel recognizes the file as such by examining its file-type. It then reads the file contents. The kernel opens the file with the name stored in the symbolic link. System administrators frequently use symbolic links to relocate data to another filesystem while maintaining the path of the parent directory. Attackers, on the other hand, use symbolic links for more nefarious purposes, as we'll cover later. Character special. Represents a byte-oriented device. It is the UNIX interface to devices that operate on a byte-by-byte basis, like a terminal device. Block special. Functions like a character special file, but for block-oriented devices such as disk drives. Socket. Allows one process to communicate with another process whether on the local system (via Inter Process Communication) or a remote machine. Programs such as Telnet, rlogin, and FTP all use sockets. Named pipe. Supports local Inter Process Communication (IPC). Because of the type of queuing used it is sometimes referred to as a FIFO (First In First Out). Each of these objects is stored in the filesystem. Protecting the filesystem from abuse is critical to the ongoing integrity of your operating system, application programs, and data. File Attributes The UNIX filesystem supports a standard set of file attributes or properties. These attributes are stored in a data structure called the inode (index node) every file has an inode. On Solaris, the inode data structure for the traditional UNIX FileSystem (UFS) is defined in /usr/include/sys/fs/ufs_inode.h. From a security perspective, the most important attributes include The owner id. The numeric user id that owns the file. The group id. The numeric group id that owns the file. Permissions. Combined with the owner id and group id, these determine the access controls on the file. Size. Measured in bytes. Time of last access. The time the file was last accessed, in seconds since 1970. Time of last modification. The time the file was last modified, in seconds since 1970. Time of last inode change. The time the file was created, in seconds since 1970. Number of hard links. The number of files that "point" at this file. The permissions attribute defines the access rights of the file owner, the group owner, and all other users on the system. The root user and file owner can control access to a file by setting permissions on the file and on the parent directories. In the standard implementation of UNIX, the root user is not subject to permission checking root can read, write, or execute any file. Note that, in UNIX, write access is equivalent to delete by definition, if you can write to the file, you can erase the contents of the file. Readers unfamiliar with filesystem permissions are encouraged to read the chmod man page. For further reading, I highly recommend Advanced Programming in the UNIX Environment, Addison-Wesley, 1992, ISBN 0-201-56317-7. Permissions in Practice To access a file by name, a user must have execute privilege in every directory contained in the file path, as well as appropriate access to the file itself. In the case of files in the current directory, a user needs execute privilege for the current directory. To be able to create a file in a directory, a user must have execute permission on every directory in the path, as well as write permission in the target directory. When it comes to deleting a file, it isn't actually necessary to be the file owner or have write permission on the file. By having write and execute permissions on the parent directory, you can delete files. This can be a "gotcha" if you're not careful. In order to understand how the various permissions are checked when a user attempts to open a file, you need to understand how process privileges work. Put simply, when you execute a program, a process is created. Associated with a process are at least six IDs: Real User ID. The numeric user id of your login account Real Group ID. The numeric group ID of your primary group (the group defined in your /etc/passwd entry) Effective User ID. The numeric user id used during file access permission checks Effective Group ID. The numeric group ID used during file access permission checks Saved Set User ID. A copy of the numeric user id saved by the exec function when you execute a program Saved Set Group ID. A copy of the numeric group ID saved by the exec function when you execute a program In addition, if you are a member of more than one UNIX group, a corresponding number of supplementary group IDs will be set. At first glance this might seem overcomplicated. To appreciate why so many IDs are required, we have to talk about a key security mechanism of UNIX, the set-uid/set-gid privilege. The Set-uid/Set-gid Privilege Normally, when you execute a program, a process is created that runs with the privileges associated with your user id. This makes sense; you shouldn't be able to interfere with files or processes belonging to another user. However, some programs need to carry out privileged operations. They can't do this if they execute under the user id of an unprivileged caller. To make a program privileged, the program owner (or root) can assign the set-uid or set-gid bit to the program via the chmod command. Unlike ordinary programs, a set-uid program executes with the privileges of the program owner not the caller. By making a program set-uid, you allow it to take actions with the authority of the program owner, on your behalf. Set-gid works the same way but, not surprisingly, for groups. A set-gid program runs with the privileges of the owning group rather than with the privileges associated with the group of the user id who called the program. Set-gid can also be set on a directory. Files subsequently created within a set-gid directory will have their group ownership set the same as that of the set-gid directory. Usually the group owner would be set to the users'primary group. This way, a group of users can share data despite being in different primary groups. An example of a set-uid program is the passwd program. When you change your password, the system needs a way to modify your password entry in /etc/shadow. This file is only accessible by root because it stores passwords; however, this prevents you from legitimately changing your password. By making the passwd program set-uid, you allow a nonprivileged user id to update its password. Without the set-uid bit, users would have to ring up the administrator to have the passwords changed. Eventually, the administrator's temper is bound to fray see the BOFH series at http://members.iinet.net.au/~bofh/ for enlightenment. In our example, the security of the shadow file is at the mercy of the passwd program. If the user running the password program can somehow influence the program in a way the programmer didn't consider, she might be able to directly modify the shadow file! Therefore, set-uid programs must be programmed defensively to avoid their being subverted by an attacker to gain extra privileges. In the case of a set-uid root program, the stakes are very high one exploitable bug will mean game over the attacker gets root privileges. The Umask Our review of file permissions would be incomplete without studying the umask. The umask determines the set of permissions that will apply to a newly created file if no permissions are explicitly specified at creation time. In other words, it's the default file permission. The umask is represented as the inverse of the file permissions. For example, if our default umask is 022, any files we create in which we don't explicitly set the file permissions will be created with 755 permissions; that is, user id has read, write, and execute permissions, whereas group ID and Other have read and execute permissions. Just remember that the umask should be set to a value opposite of the permissions you want. A common default umask value is 022. This is usually set in a system-wide login script such as /etc/profile. This can be overridden by a user who specifies a different (usually more restrictive) value in his local login script (for example, ~user/.profile). The umask command is a built-in shell command; it can be run at the shell prompt, for example, as umask 022. Every process on a UNIX system has a umask setting it doesn't just affect the users who log in interactively. When the system boots and executes the system start-up scripts, a number of network daemons (services) are started. They inherit the umask value of their parent process init usually 022. Any files they subsequently create will be given permissions set by the umask unless the programmer explicitly set permissions. The umask setting is therefore incredibly important if it is set too loosely, other users might be able to read, or in some cases, write over your files. Despite its importance, it is commonly overlooked by programmers. Filesystem Risks With the theory out of the way, let's examine the risks. The primary risks are Data disclosure. I don't want to belabor an obvious point, but this is so incredibly common that it deserves some attention. Users and programs create files in /tmp it's a digital scrap yard. If the user doesn't specify file permissions, the umask value applies. Commonly, the default umask of 022 is set, and the file is given world readable permissions any user on the system can read the file. On a typical multiuser system, it is not unusual to find copies of scripts containing database passwords, confidential business data, sensitive log information, and core files containing encrypted passwords in /tmp. The same goes for user home directories and shared areas that have not been locked down to prevent access by Other. Why break in if you can read your way to root? Unauthorized data modification/deletion. This happens in two common ways. First, through lax user practices someone sets world writable permissions on a file. The second way is via world writable directories. If I create a file in a directory that is world writable, any local user can subsequently delete/modify it. This is also true for filesystems shared via NFS. The only exception to this is directories that have the sticky bit set (such as /tmp). If the file permissions are locked down, only the owner can write to the file. This is not always obvious, because the world writable directory might be the parentof the parent of the current directory, or the parent of the parent's parent. In an extreme case, if the / directory is world writable, an attacker can replace any file on the system for example, by moving /usr/sbin out of the way and creating a replacement /usr/sbin, filled with Trojan programs of their choosing. This can easily lead to a total system compromise. The bottom line is that it's not just the parent directory that counts but every directory along the way up to slash (/)! This problem is surprisingly common on system and application directories. Resource consumption. Each filesystem is built with a finite number of inodes. When all inodes are consumed, no more files can be written to the filesystem, regardless of available free space. This can cause system daemons to crash or hang when /tmp is involved. Unless file giveaways have been disabled in the kernel, the culprit can cast the blame on another user simply by changing the ownership of the files she has created to the victim via the chown command. Consuming all free space is another approach. Temporary files with predictable filenames. Programs can be subverted to overwrite or remove arbitrary files if they create temporary files with predictable filenames in directories writable by Other (commonly /tmp). Other users can guess a filename in advance and create a symbolic link to a system file. When the program runs, it writes data to the system file resulting in data corruption. If that's the passwd file, you have a denial of service attack on your hands. This is incredibly common especially in application code and administrators'shell scripts. Named pipes that trip up the find command. By default, most UNIX systems ship with root crontab entries to run the find command. In addition, root users often run find to search for particular files. A user can create a named pipe that will cause find to hang when it reaches the pipe. The find command will open the pipe for reading and block (that is, hang) waiting for data. Because no EOF (End of File) will be sent, find will hang until it is killed. An attacker can use this method to prevent the administrator from finding the attacker's unauthorized set-uid programs. A further attack on some versions of find is to embed commands in the filename. If find passes the file to an exec command switch, the shell will interpret any shell meta characters (in this case ";") and execute the embedded commands. Privileged shell scripts that read filenames from the filesystem and blindly pass them to another program can be subverted. SNI (Secure Networks Inc.) posted an advisory way back in 1996 about this problem; it is archived here: http://lists.insecure.org/bugtraq/1996/Dec/0133.html. This weakness is still present in some commercial distributions today. World readable/writable named pipes. One method for processes to communicate with one another is through the file system using a named pipe. If the pipe has been created with weak permissions, an attacker can read and write to the named pipe subverting/crashing the process at the other end of the pipe or reading privileged data. Race conditions. Matt Bishop coined the acronym TOCTTOU (Time Of Check To Time Of Use) for a common race condition namely, when a program checks for a particular characteristic of an object and takes some action based on the assumption that the characteristic still holds true. However, if a program is subject to race conditions, an attacker can swap the object between the time the check is made and the subsequent use of the object. This tricks the program, which will then operate on the wrong object. You can see Chapter 29, "Secure Application Development, Languages, and Extensions," for more on race conditions. Filesystem Countermeasures Here are some things you can do to minimize your filesystem exposures. Give clear direction in your security policy about the need to protect the organization's data. Classify information by sensitivity and define what access controls are required. Give examples. Set the TMPDIR environment variable to a private, per-user temporary directory. Well-behaved programs check TMPDIR before using /tmp. Audit your shell scripts and change all references to publicly writable directories to your own tmp directory. For bonus points, create unique filenames without relying on the time, date, or process ID (or a weak pseudo-random number generator). Educate users about file permissions and the effect of the umask. In sensitive environments, have your users sign a usage policy that includes good stewardship of information. Ask users about their information-sharing needs. Create additional UNIX groups as necessary and enroll users as appropriate to support data sharing at a more granular level. The group's mechanism can be used very creatively think long term and design a flexible group access model. Make sure that the system-wide umask is set to 027 in the system shell start-up files as a minimum. Modify system startup files to set the umask to 027. Create a cron job to check user start-up scripts for inappropriate umask settings. Audit /tmp and other shared directories on your servers now. Perform spot checks on /tmp. Persistent offenders should be warned that they are in breach of policy. If the warnings are not heeded and the information is sensitive, consider e-mailing a summary of interesting finds to management. Disable core file creation (not to be confused with kernel crash dumps) via the ulimit command. Modern UNIX kernels will refuse to dump core when a set-uid program crashes because this might reveal sensitive information. However, privileged system daemons and application processes might dump core resulting in chunks of sensitive system files being written to world readable core file. Validate your fix by sending a QUIT signal to a expendable network service and check that it doesn't produce a core dump in its current working directory. (/proc or lsof can help find that out.) Monitor /tmp for predictable filenames using a tool such as L0pht's tmpwatch available here: http://www.atstake.com/research/tools/l0pht-watch.tar.gz. Make sure named pipes are included in your file permission checks! These are used for Inter Process Communication (IPC), so that lax permissions will allow an attacker to interact with processes in ways you don't want. Prevent file giveaways by setting CHOWN_RESTRICTED to true in the kernel configuration file. Consider using extended ACLs (where supported) via the getfacl and setfacl commands (Solaris). These extend the access information stored in the inode. They can be used to give a user access to a file or directory even if that user is not in the owning group or is not the file owner, and the file permissions deny access by "Other." But ACLs can be a real pain to administrate. Personally, I recommend that you design a good group model and only use extended ACLs when you really need to. The Set-uid Problem Programming mistakes in set-uid programs have been a real source of security headaches. A single security hole in just one set-uid root program can be all that is needed for an attacker to gain root access. The problem is widespread. We're not talking about one or two isolated instances more like a graveyard of broken set-uid programs. Again, check the SecurityFocus.com vulnerability database for set-uid problems there have been hundreds (thousands?)! The problem isn't going away, either especially in third-party programs. New set-uid vulnerabilities are being reported to Bugtraq on a weekly basis. Writing secure set-uid programs can be difficult. Just because you can program C doesn't make you a security god. Heck, even the security gods get it wrong sometimes. Take, for example, the L0pht (http://www.safermag.com/html/safer25/alerts/33.html) a group that knows its subject inside out. The C language is pretty unforgiving to the developer of set-uid programs C makes it too easy to screw up and open the barn door. Specifically, the lack of bounds checking in C has allowed many developers to write programs with buffer overflows. However, it would be pretty lame for us to blame a language for set-uid problems. After all the security pitfalls of C are well documented it's hardly a new language. Alas, the biggest source of security vulnerabilities is the n ive programmers slapping together code they think is secure. A typical UNIX distribution ships with a large number of set-uid root files averaging between 70 and 100. Now, not every line of code necessarily runs with root privilege the privilege has to be invoked by the program via a call to set-uid. But, even if the privileged lines of code are written super securely, a wily attacker can exploit a hole in the nonprivileged section of code (that is, before the call to set-uid) with devastating consequences. If the attacker exploits a buffer overflow and can force the program to make a call to set-uid boom, game over. Any code the attacker can supply for the program to execute will run with root privileges. Security-savvy programmers throw away the set-uid privilege as early as possible in the program. So, given the number of privileged programs, the administrator is left to ponder: "Where will the next vulnerability be found?" The answer is, we simply don't know. Hence the stock advice of any security textbook is to remove the set-uid bit from unnecessary privileged programs. This is much easier said than done. How do you know what is unnecessary? Sure, you know programs like passwd need to be set-uid, but what about all those others? Removing the set-uid bit has to be done with a great deal of care unless you want to have a lot of free time on your hands. A classic example of irrelevant set-uid code (at least for most people) is the KCMS (Kodak Color Management System) suite of programs. These are installed during a full install of Solaris and set-uid root. The CERT advisory CA-1996-15 describes KCMS as a set of Openwindows compliant API's and libraries to create and manage profiles that can describe and control the color performance of monitors, scanners, printers and film recorders. So, if you are a Solaris admin, have you ever used those? The only time I have used them was to demonstrate to system administrators how easily root could be compromised. Another more common example is the ping program. Ping sends an ICMP ECHO REQUEST packet to a remote system and waits for a response (ICMP ECHO REPLY) to check whether the remote system is alive (although not necessarily functioning). The standard implementation of ping requires a raw socket to be able to build the ICMP ECHO REQUEST packet. This is a privileged action because having access to a raw socket means you can create custom packets very dangerous in the wrong hands. So the ping command is set-uid root. Unfortunately, allowing mischievous users access to seemingly innocuous programs like ping can result in a security nightmare. Remember the Ping of Death? The ping command has an option whereby the user can control the size of the ICMP packet sent. It turns out that some implementations of ping allow users to send out very large ping packets that have caused remote systems to crash. Was anyone expecting that? Of course not. Hence the need to follow the least privilege principle. Only allow users to run what they need to run in order to do their job. Does every user on every system really need to be able to run network diagnostic tools? Then there are those set-uid programs that don't even need to be set-uid typically, system administration commands. The set-uid bit is redundant if only root is running it. I am not aware of any vendors that provide any guidance, or sufficient technical program documentation to help an administrator easily identify nonessential set-uid programs. Fortunately for Solaris and Linux users, there is some good information out there on locking down your set-uid programs. Truly paranoid Solaris users should check out this e-mail on the YASSP (Yet Another Solaris Security Package) mailing list from a Sun employee discussing how the company locks down Internet-facing systems: http://www.theorygroup.com/Archive/YASSP/2000/msg00548.html Solaris 2.6 set-uid lockdown information is here: http://www.ist.uwaterloo.ca/security/howto/2000-08-22.html and here: http://www.vetmed.auburn.edu/~whitej4/secureSolaris2.6.html#2.0 For Solaris 2.7 information, go here: http://ist.uwaterloo.ca/security/howto/Solaris7_set-uid.html So, how do you minimize your system's exposure to set-uid holes that are waiting in the wings? 1. Try to avoid installing the full distribution install only what you need. This is a security best practice. If the code isn't on your hard drive, then no one can use it against you. But this can be hard to fulfill in a pressure-filled environment where the focus is on getting things live. Just remember the costs of post-live lockdown. 2. List all the set-uid/set-gid programs on the system. You can do this with the following commands: 3. find / -perm -u+s -print 4. find / -perm -g+s -print 5. Find out the stated purpose of each program. You're likely to find that some of them are totally unnecessary neither you nor your users would ever need to run them. As long as these programs are not required for system operation, they can have the set-uid bit removed, or, alternatively, all access by Other can be removed (that is, chmod o-rwx file). 6. Identify the set-uid root programs that only root needs to run and remove the set-uid bit they don't need to be set-uid because you'll be running them as root. There's no point in leaving potential time bombs lying around for someone to play with. Remove the set-uid bit or access by Other (either is good). This can eliminate a large number of programs. 7. Identify set-uid programs that leak sensitive system information and thereby make an attacker's life easy for example, ps, top, and netstat. Ps and top display process information, including command-line arguments these can contain application usernames and passwords. They also help an attacker identify usage patterns, which assists timing of attacks. Similarly, netstat reveals information about your network topology (via the -R switch) and current network connections (that is, who is talking to your system). This kind of privacy disclosure can lead to client systems being attacked. Client systems are soft targets, the "low hanging fruit" of the network. They can be used as remote password sniffers (to compromise accounts on more systems), proxies to misdirect attack investigations, and conduits to other network segments that are unreachable directly (that is, they are behind a firewall or not directly attached). It's not hard to imagine the consequences if the client victim happens to belong to the system administrator level. So limit access to "leaky" set-uid programs on a strictly need-to-have basis. The side message is to secure your clients machines they can be used against you! 8. Identify the set-uid root programs that only a trusted group of users need to run (for example, network operations). Create a dedicated UNIX group and enroll the trusted users in this group. Next, change the group ownership of the set-uid programs to this group (don't change the owner though because that would make the set-uid call fail). Finally, and very importantly, remove all points of access by Other (that is, chmod o-rwx file). These include print queue management programs, network utilities, and application management interfaces. 9. Identify the set-uid root programs you think no one will ever need. Before you remove a set-uid bit, you need to be totally convinced you won't break something. In cases like these you need to profile the programs'uses that is, to log program invocation. One approach is to install an AUSCERT wrapper like the one discussed earlier. But, here, we're not going to use the wrapper for its intended purpose (although there is nothing stopping you from doing so). Instead, we're going to modify the wrapper to make a call to the logger command before the real program is called. This is unnecessary if you have C2 auditing configured and are logging calls to exec(). Review your logs after a month, and, if no relevant activity has been logged, then you probably have sufficient basis to remove the set-uid bit. You might want to leave your pager on for a while, though. 10. You should now be left with a handful of set-uid root programs that you consider essential. Modify the AUSCERT wrapper for those programs to make sure overly long arguments or environment variables cannot be specified. This won't protect you against all attacks but will protect you against some the common ones. Pat yourself on the back you've made it a lot harder for an attacker to succeed against your system. Maintenance wise, you will find that vendor patches assume a vanilla install, and, therefore, patches and upgrades clobber your changes. Always run a file integrity checker after applying updates to identify changes that way, you avoid your efforts being undermined by dumb scripts. Make sure you keep an eye on Bugtraq to keep up with new set-uid exposures, and subscribe to your vendor's security alert mailing list to ensure that you hear about patches quickly. If you have only a few trusted users on the system, you might be tempted to skip the whole set-uid removal process. Before you do, consider this: You are unwittingly making life easier for a remote attacker. If an attacker gains shell access to your machine through some 0-day (new) exploit, she will use any vulnerability she can find to elevate her privileges to root. Set-uid root programs will be at the top of her list. If you fail to bolt down your set-uid programs, an attacker will not hesitate in leveraging this against you. Understand, though, that gaining root is not always the attackers'endgame it depends on what they are trying to achieve. For example, you can store all your sensitive company data in a relational database that is owned by a user called "datamart." Clearly, the attacker only needs to target the data owner account (or privileged application accounts) to get full access to the database. This can be through password guessing, social engineering, or exploiting security bugs in set-uid application programs. Don't focus on root to the exclusion of your primary application accounts. Application software often ships with set-uid/set-gid programs. In my experience these tend to be rife with problems ignore them at your peril. It is rare to find security savvy application programmers. |