# 110.1 Perform Security Administration Tasks

Candidates should know how to review system configuration to ensure host security in accordance with local security policies.
Key Knowledge Areas
* Audit a system to find files with the suid/sgid bit set.
* Set or change user passwords and password aging information.
* Being able to use nmap and netstat to discover open ports on a system.
* Set up limits on user logins, processes and memory usage.
* Basic sudo configuration and usage.
* Prevent Root access at Boot time.
Hardening init
Many systems can (in their default configuration) be booted into single-user mode to obtain a root shell without supplying the root password. This is true, for example, for RHEL5. To prevent this, edit /etc/inittab and add the line:
ss:S:respawn:/bin/sulogin
This line tells the system that to get into state "S" (single-user) it must successfully run the program /sbin/sulogin, which asks for the root password. This change will prevent users gaining root access through a simple single-user boot.
Hardening GRUB
There are other boot-time exploits that involve modifying the options passed to the kernel by GRUB. You can prevent these by setting a GRUB password. To do this:
* Boot Linux and run grub
* At the grub prompt, enter the command md5crypt
* At the password prompt, entered the desired password
* You will be shown the password hash (beginning "$1...")
* Edit the file /boot/grub/grub.conf and add a line like this:
password --md5 $1$c1Vcl/$RlF6Wm6XF3amlhOcDTCdv.
(here you should copy and paste the password hash you got at step 4).
The effect of this line depends on where within grub.conf you put it. If you put it within one of the stanzas that correspond to specific boot menu selections (i.e. after a "title" line) then grub will always ask for the password if you choose that item from the boot menu. However, if you put it outside of these stanzas, grub will only ask for the password if you try to edit the commands at boot time. In other words, a standard boot using the existing items from the grub configuration does not require the password.
Here's an example of grub.conf where the password is inside a "title" stanza:
* default=0
* timeout=5
* splashimage=(hd0,0)/boot/grub/splash.xpm.gz
* hiddenmenu
* title Red Hat Enterprise Linux Client (2.6.18-92.el5)
* root (hd0,0)
* kernel /boot/vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet
* initrd /boot/initrd-2.6.18-92.el5.img
* password --md5 $1$c1Vcl/$RlF6Wm6XF3amlhOcDTCdv.
Hardening the BIOS
Would-be intruders that have physical access to the computer can boot from a rescue disk (or any "live" Linux CD), then mount and access the file systems on the hard drive. To prevent this the BIOS should be configured to boot only off the hard drive. When this is done, set a password on the BIOS.
Intrusion detection
A user with a legitimate account on your system who gains root access for a while (perhaps because you walked away from the computer with a root login still active) can plant a "back door" by creating an executable program that's owned by root and has the "setuid" bit turned on. This special mode bit causes the executable to run with the effective permissions of the file's owner.
You can see an example of such a program by listing the password-changing program:
* # ls -l /usr/bin/passwd
* -rwsr-xr-x 1 root root 27768 Jul 17 2006 /usr/bin/passwd
Notice the 's' in the fourth character position that indicates that the set-user-id bit is on. This program runs "setuid to root" so that ordinary (non-root) users can use it to change their passwords (which requires updating their password hash in /etc/shadow).
There are a number of legitimate setuid programs on the system. However, unexpected setuid programs (especially if owned by root) are an indication that a back door may have been created by an intruder. You can find such programs with the find command; for example:
* # find / -user root -perm +4000 2> /dev/null
* /bin/ping
* /bin/su
* /bin/mount
* /usr/bin/passwd
* /usr/bin/sudo
* /usr/bin/crontab
* /usr/bin/sudoedit
* /usr/bin/chage
* /usr/bin/rlogin
* /usr/bin/rsh
* /usr/bin/at
* /usr/bin/chfn
* /usr/bin/newgrp
* ... many lines of output deleted ...
In this example, the value "+4000" represents the octal value of the setuid mode bit.
You could implement a simple intrusion detection system by first capturing a list of these files when the system is in a pristine state:
* # find / -user root -perm +4000 2> /dev/null > /root/good-setuid-list
Subsequently you could build a new list then compare the two. In the example below a new setuid copy of bash was deliberately created:
* # find / -user root -perm +4000 2> /dev/null > /root/new-setuid-list
* # diff /root/good-setuid-list /root/new-setuid-list
* 36a37
* > /home/chris/bash
Intrusion detection tools such as tripwire and AIDE (Advanced Intrusion Detection Environment) provide a more thorough and more systematic way to detect unexpected changes to the file system. Their use is beyond the scope of LPI-1
There is also a "set group ID" bit (octal value 2000) that causes an executable to run with the effective group identity of its group. For example:
* # ls -l /usr/bin/wall
* -r-xr-sr-x 1 root tty 14792 Oct 13 2006 /usr/bin/wall
Though less common (and less dangerous) you can also search for setgid programs with find:
* # find / -perm +2000 2> /dev/null
* /usr/bin/ssh-agent
* /usr/bin/xterm
* /usr/bin/crontab
* /usr/bin/locate
* ... lines deleted ...
* /usr/bin/wall
Password Management
Users can set their own password with the passwd command:
* $ passwd
* Changing password for user chris.
* Changing password for chris
* (current) UNIX password:
* New UNIX password:
* Retype new UNIX password:
* passwd: all authentication tokens updated successfully.
Root can set or change the password of any user:
* # passwd chris
* Changing password for user chris.
* New UNIX password:
* BAD PASSWORD: it is based on a dictionary word
* Retype new UNIX password:
* passwd: all authentication tokens updated successfully.
Note that when a non-root user sets his password, a password strength check is enforced. However when root sets a user's password, the password strength check merely issues a warning; it does not prevent root from setting a weak password.
Password strength checking policies are controlled by PAM modules. For additional control over password strength, consider using the modules pam_passwdqc or pam_cracklib.
Passwords are not stored anywhere in the system as plain text. Instead, their hash is written into the file /etc/shadow. Here is a sample line:
* # grep chris /etc/shadow
* chris:$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7:::
When a user logs in and supplies his password, it is hashed, and the hash is compared with what's in /etc/shadow. Passwords may be locked and unlocked to temporarily disable and re-enable an account. Root can lock any user's password using passwd -l and unlock it using passwd -u. Locking the password simply places "!!" in front of the password hash so that it is no longer a valid hash. Unlocking the password simply removes the "!!" characters:
* # passwd -l chris
* Locking password for user chris.
* passwd: Success
* # grep chris /etc/shadow
* chris:!!$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7:::
* # passwd -u chris
* Unlocking password for user chris.
* passwd: Success.
* # grep chris /etc/shadow
* chris:$1$z5b2XDJ7$LLOh4VX5us3UMP2PMFXFp0:14869:0:99999:7:::
A password aging policy can be implemented to force a user to choose a new password every so often, or to force expiry of a user's account on a specified date. The password aging parameters are stored in fields 3 – 8 in /etc/shadow and are managed using the chage command. Options for the chage command include:
-ESet an account expiry date
-mSet the minimum number of days between password changes (0 means "no minimum")
-MSet the maximum lifetime of a password
-WSet the warning period (number of days) for a user whose password will soon expire
-lList current password aging values
Example:
* # chage -E 31-12-2011 -M 30 -W 7 chris
* # chage -l chris
* Last password change : Sep 17, 2010
* Password expires : Oct 17, 2010
* Password inactive : never
* Account expires : Jun 02, 2037
* Minimum number of days between password change : 0
* Maximum number of days between password change : 30
* Number of days of warning before password expires : 7

## Best Practices

System administrators should minimise the amount of time they spend logged in as root. They should have a normal account which they use for general work, and should transition to root only when they need to do something that requires root privilege. Transitioning to root is performed using the su (substitute user) command.
The general form of the command is:
su [-l] [user]
su will prompt for the password of the user then start a shell running with that user's identity. If no user name is specified the command starts a root shell. This is the most common usage. The '-l' option tells su to start a login shell. This shell will perform the same start-up processing as if the user was initially logging in; that is, it will set up the user's environment, including his search path. Normally, this is what you want to do. (You can also just use '-' instead of '-l'
The id command can be used to display a user's identity. and group memberships. In the example below we use it to check the identity before and after using su:
* [[Image:]]
* $ id
* uid=500(chris) gid=500(chris) groups=500(chris)
* $ su - l
* Password:
* # id
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
The sudo command can be used to grant non-root users the ability to run specific commands as root without telling them the root password. It is configured by the file.
Here's a simple example of a rule from that file:
chris ALL=(ALL) /sbin/iptables
with this rule in place, chris can elevate his privilege to run the iptables command as root:
* $ /sbin/iptables -F
* iptables v1.3.5: Permission denied (you must be root)
* $ sudo /sbin/iptables -F
* [sudo] password for chris:
The password that's being requested here is the user's own password, not the root password.
Here's a more complex rule from sudoers:
harry williambox=(william) /bin/ls, /home/william/bin/testscript.sh
This rule allows harry to run /bin/ls and /home/william/bin/testcript.sh as william, only on the machine williambox. (Restricting a sudo rule to one specific machine is useful if the sudoers file is shared network-wide). Notice that commands in a sudoers file must be specified using absolute path names.
There is a "grace period" within which sudo will not prompt for the password again. This can be set by a line in the sudoers file like this:
Defaults timestamp_timeout=10
Setting it to 0 will force sudo to prompt the a password every time. Users will probably find this annoying!
Larger, more complex sudoers files can be made easier to maintain by defining user aliases (named lists of users), host aliases (named lists of hosts) and command aliases (named lists of commands). Here's a longer example:
User_Alias ADMINS = jsmith, mikem
Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum
Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig
Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount
Host_Alias FILESERVERS = fs1, fs2
Host_Alias MAILSERVERS = smtp, smtp2
ADMINS FILESERVERS = STORAGE
chris ALL = SOFTWARE
%wheel ALL = (ALL) ALL
In this example, the command aliases effectively define roles, in terms of the set of commands which that role needs to be able to execute. The last three lines of the file are the actual rules. Taken in turn:
* Members of the user alias ADMINS can execute any of the commands in the command alias STORAGE on any of the machines listed in the host alias FILESERVERS
* chris can execute commands in the command alias SOFTWARE on all machines
* Members of the Linux wheel group can execute any command as root on any machine
The sudoers file must be edited using the command visudo. It should not be edited directly. The visudo command will verify that the file is syntactically valid before saving it.
Using sudo has a number of advantages:
* The number of people who need to know the root password is kept to a minimum
* Users spend the absolute minimum amount of time running as root (just the duration of one command) and immediately revert to non-root command prompt
* sudo logs all its actions, usually in /var/log/secure. Thus, an audit trail of all root activity is kept.
Ubuntu uses sudo exclusively for root commands. In the default configuration the root account is locked so that it is not possible to log in directly as root or to become root using su. Instead, sudo is used for everything. The key line in Ubuntu's sudoers file looks like this:
%admin ALL = (ALL) ALL
The initial account created when Ubuntu is installed is automatically made a member of the admin group.
Find and Close Ports
A machine should only run those services it's supposed to be running. Un-needed services and their associated open ports can potentially weaken security. If a service should not be running, make sure it isn't configured to start. For a RedHat style distribution (or other distribution that uses the traditional "System-V" style service management, use the chkconfig command to check and modify the status of a service. The following command sequence shows how to check the current status of the httpd daemon (web server) and to disable it.
* # chkconfig --list httpd
* httpd 0:off1:off2:on3:on4:on5:on6:off
* # chkconfig httpd off
* # chkconfig --list httpd
* httpd 0:off1:off2:off3:off4:off5:off6:off
In the example above we see that httpd is initially configured to start in run levels 2, 3, 4 and 5.
Note that chkconfig only affects the boot-time behaviour (or more accurately, the behaviour when the run-level changes). Turning a service off with chkconfig will not actually stop it running. For that you should run the service's control script:
* # /etc/init.d/httpd stop
* Stopping httpd: [ OK ]
Another way to examine which services are running is to list the open ports on the machines. You can use netstat or lsof for this; these were discussed in topic 109.3
You can also determine which ports are open using nmap. Nmap is a "network reconnaissance" tool, more often called a port scanner. Nmap will examine your open ports "from the outside", whereas netstat and lsof examine them "from the inside" of the machine. Nmap is also useful for verifying that your firewall is behaving the way you expect.
Be aware, though, that nmap can also be used in the initial stages of attacking a machine, to determine what ports are running and thus what vulnerabilities might be exploited. Because of this, running port scans on your machines (even your own machines) might be considered a hostile act, and you should obtain management permission before doing so.
The command syntax for nmap is summarised in the figure below:
Here's an example of an nmap scan:
* $ nmap 192.168.81.130
* Starting Nmap 5.00 ( http://nmap.org ) at 2010-09-17 16:09 BST
* Interesting ports on 192.168.81.130:
* Not shown: 997 closed ports
* PORT STATE SERVICE
* 22/tcp open ssh
* 80/tcp open http
* 111/tcp open rpcbind
* Nmap done: 1 IP address (1 host up) scanned in 0.20 seconds
User Limits
When the /etc/nologin file is present (it can be empty) it will prevent all users from login in to the system (except user root). If the nologin file contains a message this will be displayed after a successful authentication.
In the /etc/security/ directory are a collection of files that allow administrators to limit user CPU time, maximum file size, maximum number of connections, etc on a per-user basis.
The file /etc/security/access.conf can be used to disallow logins for groups and users from specific locations.
The file /etc/security/limits.conf can be used to set hard and soft limits for a number of resources. Each line in this file is of the form:
<domain> <type> <item> <value>
domain a user name, a group name (with @group)
type hard or soft
item:
core - limits the core file size (KB)
data - max data size (KB)
fsize - maximum filesize (KB)
memlock - max locked-in-memory address space (KB)
nofile - max number of open files
cpu - max CPU time (MIN)
nproc - max number of processes
as - address space limit
maxlogins - max number of simultaneous logins for this user
priority - the priority to run user process with
locks - max number of file locks the user can hold
This is not a complete list – see the man page for limits.conf(5) for the full list.
Here are some sample entries from limits.conf, with comments:
# User ellie can never create a file larger than 100 Mbytes
ellie hard fsize 102400
# Ellie must increase her soft limit to create file larger than 50 Mbytes
ellie soft fsize 51200
# Users in the student group cannot run more than 50 simultaneous processes
@student hard nproc 20
# By default, no users can create core files unless they up their soft limit
* soft core 0
The soft limit for a resource is the limit that's currently in force. The hard limit is the maximum that the user can increase the soft limit to.
A user can use the ulimit command (a shell built-in) to change the limits currently in force. A (non-root) user can set a soft limit to any value that's not greater than the hard limit. He can also reduce the hard limit (but not put it back up again). These limits are held within the context of that shell and are inherited by any programs started from that shell. However if a user logs out and back in again the limits will be re-established from limits.conf.
The ulimit command takes many options, including:
-a All current limits are reported
-c The maximum size of core files created
-d The maximum size of a process’s data segment
-e The maximum scheduling priority ("nice")
-f The maximum size of files written by the shell and its children
-i The maximum number of pending signals
-l The maximum size that may be locked into memory
-n The maximum number of open file descriptors
-p The pipe size in 512-byte blocks (this may not be set)
-q The maximum number of bytes in POSIX message queues
-r The maximum real-time scheduling priority
-s The maximum stack size
-t The maximum amount of cpu time in seconds
-u The maximum number of processes available to a single user
-v The maximum amount of virtual memory available to the shell
-x The maximum number of file locks
In the example below we set the maximum amount of CPU time to 100 seconds then report all values:
* $ ulimit -t 100
* $ ulimit -a
* core file size (blocks, -c) 0
* data seg size (kbytes, -d) unlimited
* scheduling priority (-e) 0
* file size (blocks, -f) unlimited
* pending signals (-i) 8192
* max locked memory (kbytes, -l) 32
* max memory size (kbytes, -m) unlimited
* open files (-n) 1024
* pipe size (512 bytes, -p) 8
* POSIX message queues (bytes, -q) 819200
* real-time priority (-r) 0
* stack size (kbytes, -s) 10240
* cpu time (seconds, -t) 100
* max user processes (-u) 8192
* virtual memory (kbytes, -v) unlimited
* file locks (-x) unlimited
Establishing ulimit settings at login time from the settings in limits.conf is performed by the PAM module pam_limits. Some systems also support the directory /etc/security/limits.d. The contents of any files found there are processed in turn as if they were appended to /etc/security/limits.conf
The following is a partial list of the used files, terms and utilities:* find
* passwd
* lsof
* nmap
* chage
* netstat
* sudo
* /etc/sudoers
* su
* usermod
* ulimit
Previous Chapter | Next Chapter