PAM—Securing Linux Boxes Everywhere
Listing 5. The /etc/security/access.conf is used by pam_access.so to decide which users are allowed to log in and from which IPs. In this case, everybody from the local network can log in, but only remoteKereki is allowed external access.
+ : ALL : 192.168. + : remoteKereki : ALL - : ALL : ALL
Listing 6. The password section of the /etc/pam.d/passwd file that enforces good practices for new passwords.
# # retry=3 allows three tries for a new password # minlen=10 requires at least ten characters # ucredit=-1 requires at least one uppercase character # lcredit=0 accepts any number of lowercase characters # dcredit=-2 requires at least two digits # ocredit=-1 requires at least one non-alphabetic symbol # password required pam_cracklib.so retry=3 minlen=10 \ ucredit=-1 lcredit=0 dcredit=-2 ocredit=-1 # # As pam_cracklib only checks passwords, but doesn't store # them, we require the standard pam_unix module for this. # The use_authtok parameter ensures pam_unix won't ask for a # password by itself, but rather will use the one provided by # pam_cracklib. # password required pam_unix.so use_authtok nullok
To get a handle on all this, let's consider an actual application. I wanted to be able to access my machine remotely with SSH, but I didn't want to allow any other users (Listing 4). So, I configured my /etc/pam.d/sshd file. See the Modules, Modules Everywhere sidebar for more details on these and other modules. Here are some of the modules I used:
pam_unix2.so: provides traditional password, rights, session and password-changing methods, in the classic UNIX way.
pam_nologin.so: disallows login if the file /etc/nologin exists.
pam_access.so: implements extra rules for access control (more later in this article on how I used this).
pam_limits.so: enforces limits for users or groups according to the file /etc/security/limits.conf.
pam_umask.so: sets the file mode creation mask for the current environment (do info umask for more information).
pam_pwcheck: enforces password-strength checks (more details on further uses of this module later in this article).
If you check your own /etc/pam.d/sshd file, it probably will look like this, except for the pam_access module, which is the interesting part. This module implements added security controls based on the /etc/security/access.conf file. I edited it in order to specify who could access my machine (Listing 5). The first line means that anybody (ALL) can log in to my machine from within the internal network at home. The second line allows the remoteKereki user to access my machine from anywhere in the world, and the final line is a catchall that disables access to anybody not included specifically in these lines. I created the remoteKereki user with minimum rights to allow myself entry to the machine, and then I execute su and work as myself or even as root, if needed. If people guess the correct password for remoteKereki, it won't help them much, because attackers still will have to guess the password for the other, more useful, users. As it is, it provides an extra barrier before intruders can do serious damage.
I had to modify /etc/ssh/sshd_config by adding a line UsePAM yes, so sshd would use the PAM configuration. I had to restart SSH with /etc/init.d/sshd restart so the configuration would be used. For even more secure connections, you also could change the SSH standard port (22) to a different value, forbid root remote logins and limit retries to hinder brute-force attacks, but those topics are beyond the scope of this article. Do man ssh_config for more details.
Left on their own, most users will (trustingly and unknowingly) use easily guessable and never-changed passwords, simplifying the job for intruders. With PAM, you can enforce several good practices for password management by using the password stack and the pam_pwcheck.so module. This module does several checks on the strength of your password:
Is the new password too short?
Is the new password too similar to the old one?
Is the new password merely the old password, reversed or rotated (for example, safe123 and 123safe)?
Is the new password the same as the old one, with only case changes (such as sEcReT and SEcrET)?
Was the new password already used before? (Old passwords are stored in the /etc/security/opasswd file.)
You can add several parameters to the module (do man pam_pwcheck for complete documentation) for extra rules, such as:
minlen=aNumber: specifies the minimum length (by default, five characters) for the new password. If you set it to zero, all password lengths are accepted.
cracklib=pathToDictionaries: allows use of the cracklib library for password checks. If the new password is in a dictionary, a simple brute-force attack quickly will guess it.
tries=aNumber: sets how many attempts to allow, if previous attempts were rejected because they were too easy.
remember=aNumber: defines how many previous passwords will be remembered.
Another module provides similar functionality, pam_cracklib.so, but it has some different parameters. For example, you might specify how many characters must differ between your old and new password and whether you want to include digits, uppercase, lowercase and nonalphabetic characters. Do man pam_cracklib for more information.