cron
and at
pam_apparmor
root
loginssudo
users
It is important that all system and vendor accounts that are not used for
logins are locked. To get a list of unlocked accounts on your system, you
can check for accounts that do not have an encrypted
password string starting with !
or
*
in the /etc/shadow
file. If you
lock an account using either passwd
-l
or
usermod
-L
, it
puts a !
in front of the encrypted password,
effectively disabling the password. Many system and
shared accounts are locked by default by having a
*
,!!
or !*
as the password field which
renders the encrypted password into an invalid string. Hence, to get a
list of all unlocked (encryptable) accounts, run the following command:
#
egrep -v ':\*|:\!' /etc/shadow | awk -F: '{print $1}'
Also make sure all accounts have an x
in the password
field in /etc/passwd
. The following command lists
all accounts that do not have a x
in the password
field:
#
grep -v ':x:' /etc/passwd
An x
in the password field means that the password
has been shadowed, for example, the encrypted password needs to be looked
up in the /etc/shadow
file. If the password field in
/etc/passwd
is empty, then the system does not look
up the shadow file and it prompts the user for a password at the
login prompt.
All system or vendor accounts that are not being used by users, applications, by the system or by daemons should be removed from the system. You can use the following command to find out if there are any files owned by a specific account:
#
find / -path /proc -prune -o -user ACCOUNT -ls
The -prune
option in this example is used to skip the
/proc file system. If you are sure that an account can be deleted, you
can remove the account using the following command:
#
userdel -r ACCOUNT
Without the -r
option, userdel
does
not delete the user's home directory and mail spool
(/var/spool/mail/USER
).
Many system accounts do not have a home directory.
Password expiration is a general best practice, but might need to be excluded for certain system and shared accounts (for example, Oracle). Expiring passwords on those accounts could lead to system outages if the application account expires.
Typically a corporate policy should be developed that dictates rules/procedures regarding password changes for system and shared accounts. However, normal user account passwords should expire automatically. The following example shows how password expiration can be set up for individual user accounts.
The following files and parameters in the table can be used when a new
account is created with the useradd
command. Settings
such as these are stored for each user account in the
/etc/shadow
file. If using the YaST tool
( ) to add users, the settings
are available on a per-user basis. Here are the various
settings, some of which can also be system-wide (for example,
modification of /etc/login.defs
and
/etc/default/useradd
):
|
|
Maximum number of days a password is valid. |
|
|
Minimum number of days before a user can change the password since the last change. |
|
|
Number of days between the last password change and the next password change reminder. |
|
|
Number of days after password expiration until the account is disabled. |
|
|
Account expiration date in the format YYYY-MM-DD. |
Users created before these modifications are not affected.
Ensure that the above parameters are changed in the
/etc/login.defs
and
/etc/default/useradd
files. A review of the
/etc/shadow
file shows how these settings are
stored after adding a user.
To create a new user account, execute the following command:
#
useradd -c "TEST_USER" -g USERS TEST
The -g
option specifies the primary group for this
account:
#
id TEST
uid=509(test) gid=100(users) groups=100(users)
The settings in /etc/login.defs
and
/etc/default/useradd
are recorded for the test user
in the /etc/shadow
file as follows:
#
grep TEST /etc/shadow
test:!!:12742:7:60:7:14::
Password aging can be modified at any time by use of the
chage
command. To disable password aging for system and
shared accounts, you can run the following chage
command:
#
chage -M -1 SYSTEM_ACCOUNT_NAME
To get password expiration information:
#
chage -l SYSTEM_ACCOUNT_NAME
For example:
#
chage -l TEST
Minimum: 7
Maximum: 60
Warning: 7
Inactive: 14
Last Change: Jan 11, 2015
Password Expires: Mar 12, 2015
Password Inactive: Mar 26, 2015
Account Expires: Never
On an audited system, it is important to restrict people from using simple passwords that can be cracked too easily. Writing down complex passwords is all right if stored securely. Some argue that strong passwords protect you against dictionary attacks, and those types of attacks can be defeated by locking accounts after a few failed attempts. However, this is not always an option. If set up like this, locking system accounts could bring down your applications and systems, which would be nothing short of a denial-of-service attack—another issue.
At any rate, it is important to practice effective password management security. Most companies require that passwords have at least a number, one lowercase letter, and one uppercase letter. Policies vary, but maintaining a balance between password strength/complexity and management can be difficult.
Linux-PAM (Pluggable Authentication Modules for Linux) is a suite of shared libraries that enable the local system administrator to choose how applications authenticate users.
It is strongly recommended to familiarize oneself with the capabilities of PAM and how this architecture can be leveraged to provide the best authentication setup for an environment. This configuration can be done once, and implemented across all systems (a standard), or can be enhanced for individual hosts (enhanced security—by host/service/application). The key is to realize how flexible the architecture is.
To learn more about the PAM architecture, find PAM documentation in
the /usr/share/doc/packages/pam
directory (in
a variety of formats).
The following discussions are examples of how to modify the default PAM stacks—specifically around password policies—for example password strength, password re-use, and account locking. While these are only a few of the possibilities, they serve as a good start and demonstrate PAM's flexibility.
pam-config
limitations
The pam-config
tool can be used to configure the
common-{account,auth,password,session} PAM configuration files, which
contain global options. These files include the following comment:
# This file is autogenerated by pam-config. All changes # will be overwritten.
Individual service files, such as login, password, sshd
,
and su
must be edited directly. You can elect to edit
all files directly, and not use pam-config
, though
pam-config
includes useful features such as converting
an older configuration, updating your current configuration, and sanity checks.
For more information, see man 8 pam-config
.
openSUSE Leap can leverage the
pam_cracklib
library to test
for weak passwords—and to suggest using a stronger one if it
determines obvious weakness. The following parameters represent an
example that could be part of a corporate password policy or something
required because of audit constraints.
The PAM libraries follow a defined flow. The best way to design the perfect stack usually is to consider all of the requirements and policies and draw out a flow chart.
|
|
Minimum length of password is 8 |
|
|
Minimum number of lowercase letters is 1 |
|
|
Minimum number of uppercase letters is 1 |
|
|
Minimum number of digits is 1 |
|
|
Minimum number of other characters is 1 |
To set up these password restrictions, use the
pam-config
tool to specify the parameters you want
to configure. For example, the minimum length parameter could be
modified like this:
>
sudo
pam-config -a --cracklib-minlen=8 --cracklib-retry=3 \ --cracklib-lcredit=-1 --cracklib-ucredit=-1 --cracklib-dcredit=-1 \ --cracklib-ocredit=-1 --cracklib
Now verify that the new password restrictions work for new passwords.
Log in to a non-root account and change the password using the
passwd
command. Note that the above requirements
are not enforced if you run the passwd
command
under root.
The pam_pwhistory module can be used to configure the number of previous passwords that cannot be reused. The following command implements password restrictions on a system so that a password cannot be reused for at least six months:
>
sudo
pam-config -a --pwhistory --pwhistory-remember=26
Recall that in the section
Section 14.2, “Enabling password aging” we set
PASS_MIN_DAYS
to 7
, which
specifies the minimum number of days allowed between password changes.
Therefore, if pam_unix
is configured to
remember 26
passwords, then the previously used
passwords cannot be reused for at least six months (26*7 days).
The PAM configuration (/etc/pam.d/common-password
)
resulting from the pam-config
command looks like the
following:
auth required pam_env.so auth required pam_unix.so try_first_pass account required pam_unix.so try_first_pass password requisite pam_cracklib.so password required pam_pwhistory.so remember=26 password optional pam_gnome_keyring.so use_authtok password required pam_unix.so use_authtok nullok shadow try_first_pass session required pam_limits.so session required pam_unix.so try_first_pass session optional pam_umask.so
Locking accounts after a defined number of failed ssh, login, su, or sudo
attempts is a common security practice. However, this could lead to
outages if an application, admin, or root
user is locked out.
Password failure counts can easily be abused to cause denial-of-service attacks by deliberately creating login failures.
Only use password failure counts if you have to. Restrict locking to the necessary minimum, and do not lock critical accounts. Keep in mind that locking not only applies to human users but also to system accounts used to provide services.
openSUSE Leap does not lock accounts by default, but provides PAM module
pam_tally2
to easily implement password failure counts.
Add the following line to the top of /etc/pam.d/login
to lock out all users (except for root
) after six failed logins, and
to automatically unlock the accounts after ten minutes:
auth required pam_tally2.so deny=6 unlock_time=600
This is an example of a complete /etc/pam.d/login
file:
#%PAM-1.0 auth requisite pam_nologin.so auth include common-auth auth required pam_tally2.so deny=6 unlock_time=600 account include common-account account required pam_tally2.so password include common-password session required pam_loginuid.so session include common-session #session optional pam_lastlog.so nowtmp showfailed session optional pam_mail.so standard
You can also lock out root
, though obviously you must be very
certain you want to do this:
auth required pam_tally2.so deny=6 even_deny_root unlock_time=600
You can define a different lockout time for root:
auth required pam_tally2.so deny=6 root_unlock_time=120 unlock_time=600
If you want to require the administrator to unlock accounts, leave out the
unlock_time
option. The next two example commands
display the number of failed login attempts and how to unlock a user
account:
>
sudo
pam_tally2 -u username
Login Failures Latest failure From username 6 12/17/19 13:49:43 pts/1>
sudo
pam_tally2 -r -u username
The default location for attempted accesses is recorded in
/var/log/tallylog
.
If the user succeeds in logging in after the login timeout expires, or after the administrator resets their account, the counter resets to 0.
Configure other login services to use pam_tally2
in
their individual configuration files in /etc/pam.d/
:
sshd, su, sudo, sudo-i
, and su-l
.
root
logins #Edit source
By default, the root
user is assigned a password
and can log in using various methods—for example, on a local
terminal, in a graphical session, or remotely via SSH. These methods
should be restricted as far as possible. Shared usage of the root account
should be avoided. Instead, individual administrators should use tools such as
su
or sudo
(for more information,
type man 1 su
or man 8 sudo
) to obtain elevated
privileges. This allows associating root
logins with particular
users. This also adds another layer of security; not only the root
password, but both the root
and the password of
an administrator's regular account would need to be compromised to gain full root
access. This section explains how to limit direct root logins on the different
levels of the system.
TTY devices provide text-mode system access via the console. For desktop
systems these are accessed via the local keyboard or—in case of server
systems—via input devices connected to a KVM switch or a remote
management card (for example, ILO and DRAC).
By default, Linux offers six different consoles, which can be switched to
via the key combinations
Alt–F1 to
Alt–F6, when
running in text mode, or
Ctrl–Alt–F1 to
Ctrl–Alt–F6
when running in a graphical session. The
associated terminal devices are named tty1
to tty6
.
The following steps restrict root access to the first TTY. Even this access method is only meant for emergency access to the system and should never be used for everyday system administration tasks.
The steps shown here are tailored towards PC architectures (x86 and
AMD64/Intel 64). On architectures such as POWER, different terminal
device names than tty1
can be used. Be careful not to
lock yourself out by specifying wrong terminal device names.
You can determine the device name of the terminal you are currently
logged in to by running the tty
command. Be careful
not to do this in a virtual terminal, such as via SSH or in a graphical
session (device names /dev/pts/N
),
but only from an actual login terminal reachable via
Alt–FN.
Ensure that the PAM stack configuration file /etc/pam.d/login
contains the pam_securetty
module in the auth
block:
auth requisite pam_nologin.so auth [user_unknown=ignore success=ok ignore=ignore auth_err=die default=bad] pam_securetty.so noconsole auth include common-auth
This includes the pam_securetty
module during the
authentication process on local consoles, which restricts root
to logging in
only on TTY devices that are listed in the file /etc/securetty
.
Remove all entries from /etc/securetty
except one.
This limits the access to TTY devices for root.
# # This file contains the device names of tty lines (one per line, # without leading /dev/) on which root is allowed to login. # tty1
Check whether logins to other terminals are rejected for
root
. A login on tty2
, for example, should be
rejected immediately, without even querying the account password.
Also make sure that you can still successfully log in to
tty1
and thus that root
is not locked out of
the system.
Do not add the pam_securetty
module to the
/etc/pam.d/common-auth
file. This would
break the su
and sudo
commands,
because these tools would then also reject root
authentications.
These configuration changes also cause root logins on serial
consoles such as /dev/ttyS0
to be denied. In case you
require such use cases, you need to list the respective TTY devices
additionally in the /etc/securetty
file.
To improve security on your server, avoid using graphical
environments at all. Graphical programs are often
not designed to be run as root
and can
contain security issues than console programs. If you require a graphical
login, use a non-root
login. Configure your system to disallow
root
from logging in to graphical sessions.
To prevent root
from logging in to graphical sessions, you
can apply the same basic steps as outlined in
Section 14.5.1, “Restricting local text console logins”.
Just add the pam_securetty
module to the PAM
stack file belonging to the display manager—for example,
/etc/pam.d/gdm
for GDM. The graphical
session also runs on a TTY device: by default, tty7
.
Therefore, if you restrict root
logins to tty1
,
then root
is denied login in the graphical session.
By default, the root
user is also allowed to log
in to a machine remotely via the SSH network protocol (if the SSH port is
not blocked by the firewall). To restrict this, make the following
change to the OpenSSH configuration:
Edit /etc/ssh/sshd_config
and adjust the following parameter:
PermitRootLogin no
Restart the sshd
service to make the changes effective:
systemctl restart sshd.service
Using the PAM pam_securetty
module is not suitable in
case of OpenSSH, because not all SSH logins go through the PAM
stack during authorization (for example, when using SSH public-key authentication).
Additionally, an attacker could differentiate between a wrong password
and a successful login that was only rejected later on by policy.
sudo
users #Edit source
The sudo
command allows users to execute commands in the
context of another user, typically the root
user. The
sudo
configuration consists of a rule-set that defines
the mappings between commands to execute and their allowed source and target
users and groups. The configuration is stored in the file
/etc/sudoers
.
By default, sudo
asks for the root
password on
SUSE systems. Unlike su
however,
sudo
remembers the password and allows further commands
to be executed as root
without asking for the password again for five
minutes. Therefore, sudo
should be enabled for selected
administrator users only.
sudo
for normal users #
Edit file /etc/sudoers
, for example by executing
visudo
.
Comment out the line that allows every user to run every command as long as they know the password of the user they want to use. Afterwards, it should look like this:
#ALL ALL=(ALL) ALL # WARNING! Only use this together with 'Defaults targetpw'!
Uncomment the following line:
%wheel ALL=(ALL) ALL
This limits the functionality described above to members of the group
wheel
. You can use a different
group as wheel
might have other
implications that might not be suitable depending on your setup.
Add users that should be allowed to use sudo
to the
chosen group. To add the user tux
to the group
wheel
, use:
usermod -aG wheel tux
To get the new group membership, users have to log out and back in again.
Verify the change by running a command with a user not in the group you have chosen for access control. You should see the error message:
wilber is not in the sudoers file. This incident will be reported.
Next, try the same with a member of the group. They should still be able
to execute commands via sudo
.
This configuration only limits the sudo
functionality. The su
command is still available to all
users. If there are other ways to access the system, users with knowledge of
the root
password can easily execute commands via this vector.
It can be a good idea to terminate an interactive shell session after a certain period of inactivity. For example, to prevent open, unguarded sessions, or to avoid wasting system resources.
By default, there is no inactivity timeout for shells. Nothing happens if a shell stays open and unused for days or even years. However, it is possible to configure most shells so that idle sessions terminate automatically after a certain amount of time. The following example shows how to set an inactivity timeout for several common types of shells.
The inactivity timeout can be configured for login shells only or for all interactive shells. In the latter case, the inactivity timeout runs individually for each shell instance. This means that timeouts accumulate. When a sub- or child-shell is started, a new timeout begins for the sub- or child-shell, and only afterwards the timeout of the parent continues running.
The following table contains configuration details for a selection of common shells shipped with openSUSE Leap:
package | shell personalities | shell variable | time unit | readonly setting | config path (only login shell) | config path (all shells) |
---|---|---|---|---|---|---|
|
|
| seconds |
|
|
|
|
|
| seconds |
|
|
|
|
|
| minutes |
|
|
|
|
|
| seconds |
|
|
|
Every listed shell supports an internal timeout shell variable that can be set to a specific time value to cause the inactivity timeout. If you want to prevent users from overriding the timeout setting, you can mark the corresponding shell timeout variable as read-only. The corresponding variable declaration syntax is also found in the table above.
This feature is only helpful for avoiding risks if a user is forgetful or follows unsafe practices. It does not protect against hostile users. The timeout only applies to interactive wait states of a shell. A malicious user can always find ways to circumvent the timeout and keep their session open regardless.
To configure the inactivity timeout, you need to add the matching timeout
variable declaration to each shell's start-up script. Use either the path for
login shells only, or the one for all shells, as listed in the table. The
following example uses paths and settings that are suitable for
bash
and ksh
to set up a read-only login shell timeout that cannot be overridden by users.
Create the file /etc/profile.d/timeout.sh
with the
following content:
# /etc/profile.d/timeout.sh for SUSE Linux # # Timeout in seconds until the bash/ksh session is terminated # in case of inactivity. # 24h = 86400 sec readonly TMOUT=86400
We recommend using the screen
tool to
detach sessions before logging out. screen
sessions
are not terminated and can be re-attached whenever required. An active
session can be locked without logging out (read about Ctrl–A–X / lockscreen
in
man screen
for details).
Linux allows you to set limits on the amount of system resources that users and groups can consume. This is also useful if bugs in programs cause them to use up too many resources (for example, memory leaks), slow down the machine, or even render the system unusable. Incorrect settings can allow programs to use too many resources, which might make the server unresponsive to new connections or even local logins (for example, if a program uses up all available file handles on the host). This can also be a security concern if someone is allowed to consume all system resources and therefore cause a denial-of-service attack—either unplanned, or worse, planned. Setting resource limits for users and groups might be an effective way to protect systems, depending on the environment.
The following example demonstrates the practical usage of setting or
restricting system resource consumption for an Oracle user account. For a
list of system resource settings, see
/etc/security/limits.conf
or man
limits.conf
.
Most shells, such as Bash, provide control over various resources (for example, the maximum allowable number of open file descriptors or the maximum number of processes) that are available on a per-user basis. To examine all current limits in the shell, execute:
#
ulimit -a
For more information on ulimit
for the Bash shell,
examine the Bash man pages.
Setting “hard” and “soft” limits might not have
the expected results when using an SSH session. To see valid behavior, it
might be necessary to log in as root, and then su
to the
ID with limits (for example, Oracle
in these examples).
Resource limits should also work assuming the application was started
automatically during the boot process. It might be necessary to set
UsePrivilegeSeparation
in
/etc/ssh/sshd_config
to no
and
restart the SSH daemon (systemctl restart sshd
)
if it seems that the changes to resource limits are not working (via
SSH). However, this is not generally recommended, as it weakens a system's
security.
ssh
You can add extra security to your server by disabling password
authentication for SSH. Remember that you need to have SSH keys
configured, otherwise you cannot access the server. To disable password
login, add the following lines to
/etc/ssh/sshd_config
:
UseLogin no UsePAM no PasswordAuthentication no PubkeyAuthentication yes
In this example, a change to the number of file handles or open files
that the user oracle
can use is made by editing
/etc/security/limits.conf
as root
making the
following changes:
oracle soft nofile 4096 oracle hard nofile 63536
The soft limit in the first line defines the limit on the number of file
handles (open files) that the
oracle
user has after
login. If the user sees error messages about running out of file handles,
then the user can increase the number of file handles like in this
example up to the hard limit (in this example 63536) by executing:
#
ulimit -n 63536
You can set the soft and hard limits higher if necessary.
It is important to be judicious with the usage of ulimits. Allowing a
“hard” limit for nofile
for a user that
is equal to the kernel limit (/proc/sys/fs/file-max
)
is bad. If the user consumes all the available file handles, the
system cannot initiate new logins, since it is not possible to access
the PAM modules required to perform a login.
You also need to ensure that pam_limits
is either
configured globally in /etc/pam.d/common-auth
, or
for individual services like SSH, su, login and telnet in:
/etc/pam.d/sshd (for SSH) |
/etc/pam.d/su (for su) |
/etc/pam.d/login (local logins and telnet) |
If you do not want to enable it for all logins, there is a specific PAM
module that reads the /etc/security/limits.conf
file. Entries in PAM configuration directives have entries like:
session required /lib/security/pam_limits.so session required /lib/security/pam_unix.so
Changes are not immediate and require a new login session:
#
su - oracle>
ulimit -n 4096
These examples are specific to the Bash shell;
ulimit
options are different for other shells. The
default limit for the user oracle
is
4096
. To increase the number of file handles the user
oracle
can use to 63536
, execute:
#
su - oracle>
ulimit -n 4096>
ulimit -n 63536>
ulimit -n 63536
Making this permanent requires the addition of the setting,
ulimit -n 63536
, (again, for Bash) to the user's
profile (~/.bashrc
or
~/.profile
file), which is the user start-up file for
the Bash shell on openSUSE Leap (to verify your shell, run:
echo $SHELL
). To do this you could run the following commands for the
Bash shell of the user oracle
:
#
su - oracle>
cat >> ~oracle/.bash_profile << EOF ulimit -n 63536 EOF
It is often necessary to place a banner on login screens on all servers for legal/audit policy reasons or to give security instructions to users.
To print a login banner after a user
logs in on a text based terminal, for example, using SSH or on a local
console, you can use the file /etc/motd
(motd =
message of the day). The file exists by default on openSUSE Leap, but
it is empty. Simply add content to the file that is applicable/required
by the organization.
Try to keep the login banner content to a single terminal page (or less), as it scrolls the screen if it does not fit, making it more difficult to read.
You can also have a login banner printed before a
user logs in on a text based terminal. For local console
logins, you can edit the /etc/issue
file, which
causes the banner to be displayed before the login prompt. For logins via
SSH, you can edit the “Banner” parameter in the
/etc/ssh/sshd_config
file, which then
appropriately displays the banner text before the SSH login prompt.
For graphical logins via GDM, you can follow
the GNOME admin guide to set up a login banner. Furthermore,
you can make the following changes to require a user to acknowledge the
legal banner by selecting or .
Edit the /etc/gdm/Xsession
file and add the
following lines at the beginning of the script:
if ! /usr/bin/gdialog --yesno '\nThis system is classified...\n' 10 10; then /usr/bin/gdialog --infobox 'Aborting login' exit 1; fi
The text This system is classified... needs to be replaced with the desired banner text. This dialog does not prevent a login from progressing. For more information about GDM scripting, refer to the GDM Admin Manual.
Here is a list of commands you can use to get data about user logins:
who
.
Lists currently logged in users.
w
.
Shows who is logged in and what they are doing.
last
.
Shows a list of the most recent logged in users, including login time, logout time,
login IP address, etc.
lastb
.
Same as last
, except that by default it shows
/var/log/btmp
, which contains all the bad login
attempts.
lastlog
.
This command reports data maintained in
/var/log/lastlog
, which is a record of the last
time a user logged in.
ac
.
Available after installing the acct
package.
Prints the connect time in hours on a per-user basis or daily basis,
etc. This command reads /var/log/wtmp
.
dump-utmp
.
Converts raw data from /var/run/utmp or
/var/log/wtmp
into ASCII-parseable format.
Also check the /var/log/messages
file, or the output
of journalctl
if no logging facility is running. See
Book “Reference”, Chapter 11 “journalctl
: query the systemd
journal” for more information on the systemd
journal.