contains 14 rules |
System Settings
[ref]groupContains rules that check correct system settings. |
contains 14 rules |
Account and Access Control
[ref]groupIn traditional Unix security, if an attacker gains
shell access to a certain login account, they can perform any action
or access any file to which that account has access. Therefore,
making it more difficult for unauthorized people to gain shell
access to accounts, particularly to privileged accounts, is a
necessary part of securing a system. This section introduces
mechanisms for restricting access to accounts under
Oracle Linux 7. |
contains 4 rules |
Protect Accounts by Restricting Password-Based Login
[ref]groupConventionally, Unix shell accounts are accessed by
providing a username and password to a login program, which tests
these values for correctness using the /etc/passwd and
/etc/shadow files. Password-based login is vulnerable to
guessing of weak passwords, and to sniffing and man-in-the-middle
attacks against passwords entered over a network or at an insecure
console. Therefore, mechanisms for accessing accounts by entering
usernames and passwords should be restricted to those which are
operationally necessary. |
contains 2 rules |
Verify Proper Storage and Existence of Password
Hashes
[ref]groupBy default, password hashes for local accounts are stored
in the second field (colon-separated) in
/etc/shadow . This file should be readable only by
processes running with root credentials, preventing users from
casually accessing others' password hashes and attempting
to crack them.
However, it remains possible to misconfigure the system
and store password hashes
in world-readable files such as /etc/passwd , or
to even store passwords themselves in plaintext on the system.
Using system-provided tools for password change/creation
should allow administrators to avoid such misconfiguration. |
contains 2 rules |
Verify All Account Password Hashes are Shadowed
[ref]ruleIf any password hashes are stored in /etc/passwd (in the second field,
instead of an x or * ), the cause of this misconfiguration should be
investigated. The account should have its password reset and the hash should be
properly stored, or the account should be deleted entirely. Rationale:The hashes for all user account passwords should be stored in
the file /etc/shadow and never in /etc/passwd ,
which is readable by all users. |
Prevent Log In to Accounts With Empty Password
[ref]ruleIf an account is configured for password authentication
but does not have an assigned password, it may be possible to log
into the account without authentication. Remove any instances of the nullok
option in /etc/pam.d/system-auth to
prevent logins with empty passwords. Rationale:If an account has an empty password, anyone could log in and
run commands with the privileges of that account. Accounts with
empty passwords should never be used in operational environments. References:
5.5.2, 3.1.1, 3.1.5, CCI-000366, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), AC-6, IA-5(b), IA-5(c), IA-5(1)(a), Req-8.2.3, SRG-OS-000480-GPOS-00227 Remediation Shell script: (show)
sed --follow-symlinks -i 's/\<nullok\>//g' /etc/pam.d/system-auth
sed --follow-symlinks -i 's/\<nullok\>//g' /etc/pam.d/password-auth
Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | medium |
---|
Strategy: | configure |
---|
- name: "Prevent Log In to Accounts With Empty Password - system-auth"
replace:
dest: /etc/pam.d/system-auth
follow: yes
regexp: 'nullok'
tags:
- no_empty_passwords
- high_severity
- configure_strategy
- low_complexity
- medium_disruption
- NIST-800-53-AC-6
- NIST-800-53-IA-5(b)
- NIST-800-53-IA-5(c)
- NIST-800-53-IA-5(1)(a)
- NIST-800-171-3.1.1
- NIST-800-171-3.1.5
- PCI-DSS-Req-8.2.3
- CJIS-5.5.2
- name: "Prevent Log In to Accounts With Empty Password - password-auth"
replace:
dest: /etc/pam.d/password-auth
follow: yes
regexp: 'nullok'
tags:
- no_empty_passwords
- high_severity
- configure_strategy
- low_complexity
- medium_disruption
- NIST-800-53-AC-6
- NIST-800-53-IA-5(b)
- NIST-800-53-IA-5(c)
- NIST-800-53-IA-5(1)(a)
- NIST-800-171-3.1.1
- NIST-800-171-3.1.5
- PCI-DSS-Req-8.2.3
- CJIS-5.5.2
|
Secure Session Configuration Files for Login Accounts
[ref]groupWhen a user logs into a Unix account, the system
configures the user's session by reading a number of files. Many of
these files are located in the user's home directory, and may have
weak permissions as a result of user error or misconfiguration. If
an attacker can modify or even read certain types of account
configuration information, they can often gain full access to the
affected user's account. Therefore, it is important to test and
correct configuration file permissions for interactive accounts,
particularly those of privileged users such as root or system
administrators. |
contains 2 rules |
Ensure that No Dangerous Directories Exist in Root's Path
[ref]groupThe active path of the root account can be obtained by
starting a new root shell and running:
# echo $PATH
This will produce a colon-separated list of
directories in the path.
Certain path elements could be considered dangerous, as they could lead
to root executing unknown or
untrusted programs, which could contain malicious
code.
Since root may sometimes work inside
untrusted directories, the . character, which represents the
current directory, should never be in the root path, nor should any
directory which can be written to by an unprivileged or
semi-privileged (system) user.
It is a good practice for administrators to always execute
privileged commands by typing the full path to the
command. |
contains 2 rules |
Ensure that Root's Path Does Not Include Relative Paths or Null Directories
[ref]ruleEnsure that none of the directories in root's path is equal to a single
. character, or
that it contains any instances that lead to relative path traversal, such as
.. or beginning a path without the slash (/ ) character.
Also ensure that there are no "empty" elements in the path, such as in these examples:
PATH=:/bin
PATH=/bin:
PATH=/bin::/sbin
These empty elements have the same effect as a single . character.Rationale:Including these entries increases the risk that root could
execute code from an untrusted location. |
Ensure that Root's Path Does Not Include World or Group-Writable Directories
[ref]ruleFor each element in root's path, run:
# ls -ld DIR
and ensure that write permissions are disabled for group and
other.Rationale:Such entries increase the risk that root could
execute code provided by unprivileged users,
and potentially malicious code. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | medium |
---|
Strategy: | restrict |
---|
- name: "Fail if user is not root"
fail:
msg: 'Root account required to read root $PATH'
when: ansible_user != "root"
tags:
- accounts_root_path_dirs_no_write
- unknown_severity
- restrict_strategy
- low_complexity
- medium_disruption
- NIST-800-53-CM-6(b)
- name: "Get root paths which are not symbolic links"
shell: 'tr ":" "\n" <<< "$PATH" | xargs -I% find % -maxdepth 0 -type d'
changed_when: False
failed_when: False
register: root_paths
when: ansible_user == "root"
check_mode: no
tags:
- accounts_root_path_dirs_no_write
- unknown_severity
- restrict_strategy
- low_complexity
- medium_disruption
- NIST-800-53-CM-6(b)
- name: "Disable writability to root directories"
file:
path: "{{item}}"
mode: "g-w,o-w"
with_items: "{{ root_paths.stdout_lines }}"
when: root_paths.stdout_lines is defined
tags:
- accounts_root_path_dirs_no_write
- unknown_severity
- restrict_strategy
- low_complexity
- medium_disruption
- NIST-800-53-CM-6(b)
|
File Permissions and Masks
[ref]groupTraditional Unix security relies heavily on file and
directory permissions to prevent unauthorized users from reading or
modifying files to which they should not have access.
Several of the commands in this section search filesystems
for files or directories with certain characteristics, and are
intended to be run on every local partition on a given system.
When the variable PART appears in one of the commands below,
it means that the command is intended to be run repeatedly, with the
name of each local partition substituted for PART in turn.
The following command prints a list of all xfs partitions on the local
system, which is the default filesystem for Red Hat Enterprise Linux
7 installations:
$ mount -t xfs | awk '{print $3}'
For any systems that use a different
local filesystem type, modify this command as appropriate. |
contains 6 rules |
Verify Permissions on Important Files and
Directories
[ref]groupPermissions for many files on a system must be set
restrictively to ensure sensitive information is properly protected.
This section discusses important
permission restrictions which can be verified
to ensure that no harmful discrepancies have
arisen. |
contains 4 rules |
Ensure All SGID Executables Are Authorized
[ref]ruleThe SGID (set group id) bit should be set only on files that were
installed via authorized means. A straightforward means of identifying
unauthorized SGID files is determine if any were not installed as part of an
RPM package, which is cryptographically verified. Investigate the origin
of any unpackaged SGID files. Rationale:Executable files with the SGID permission run with the privileges of
the owner of the file. SGID files of uncertain provenance could allow for
unprivileged users to elevate privileges. The presence of these files should be
strictly controlled on the system. |
Ensure No World-Writable Files Exist
[ref]ruleIt is generally a good idea to remove global (other) write
access to a file when it is discovered. However, check with
documentation for specific applications before making changes.
Also, monitor for recurring world-writable files, as these may be
symptoms of a misconfigured application or user account. Finally,
this applies to real files and not virtual files that are a part of
pseudo file systems such as sysfs or procfs . Rationale:Data in world-writable files can be modified by any
user on the system. In almost all circumstances, files can be
configured using a combination of user and group permissions to
support whatever legitimate access is needed without the risk
caused by world-writable files. |
Verify that All World-Writable Directories Have Sticky Bits Set
[ref]ruleWhen the so-called 'sticky bit' is set on a directory,
only the owner of a given file may remove that file from the
directory. Without the sticky bit, any user with write access to a
directory may remove any file in the directory. Setting the sticky
bit prevents users from removing each other's files. In cases where
there is no reason for a directory to be world-writable, a better
solution is to remove that permission rather than to set the sticky
bit. However, if a directory is used by a particular application,
consult that application's documentation instead of blindly
changing modes.
To set the sticky bit on a world-writable directory DIR, run the
following command:
$ sudo chmod +t DIR Rationale:Failing to set the sticky bit on public directories allows unauthorized users to delete files in the directory structure.
The only authorized public directories are those temporary directories supplied with the system,
or those designed to be temporary file repositories. The setting is normally reserved for directories
used by the system, by users for temporary file storage (such as /tmp ), and for directories
requiring global read/write access. |
Ensure All SUID Executables Are Authorized
[ref]ruleThe SUID (set user id) bit should be set only on files that were
installed via authorized means. A straightforward means of identifying
unauthorized SGID files is determine if any were not installed as part of an
RPM package, which is cryptographically verified. Investigate the origin
of any unpackaged SUID files. Rationale:Executable files with the SUID permission run with the privileges of
the owner of the file. SUID files of uncertain provenance could allow for
unprivileged users to elevate privileges. The presence of these files should be
strictly controlled on the system. |
Restrict Partition Mount Options
[ref]groupSystem partitions can be mounted with certain options
that limit what files on those partitions can do. These options
are set in the /etc/fstab configuration file, and can be
used to make certain types of malicious behavior more difficult. |
contains 2 rules |
Add nosuid Option to /dev/shm
[ref]ruleThe nosuid mount option can be used to prevent execution
of setuid programs in /dev/shm . The SUID and SGID permissions should not
be required in these world-writable directories.
Add the nosuid option to the fourth column of
/etc/fstab for the line which controls mounting of
/dev/shm .
Rationale:The presence of SUID and SGID executables should be tightly controlled. Users
should not be able to execute SUID or SGID binaries from temporary storage partitions. Remediation Shell script: (show)
function include_mount_options_functions {
:
}
# $1: mount point
# $2: new mount point option
function ensure_mount_option_in_fstab {
local _mount_point="$1" _new_opt="$2" _mount_point_match_regexp="" _previous_mount_opts=""
_mount_point_match_regexp="$(get_mount_point_regexp "$_mount_point")"
if [ $(grep "$_mount_point_match_regexp" /etc/fstab | grep -c "$_new_opt" ) -eq 0 ]; then
_previous_mount_opts=$(grep "$_mount_point_match_regexp" /etc/fstab | awk '{print $4}')
sed -i "s|\(${_mount_point_match_regexp}.*${_previous_mount_opts}\)|\1,${_new_opt}|" /etc/fstab
fi
}
# $1: mount point
function get_mount_point_regexp {
printf "[[:space:]]%s[[:space:]]" "$1"
}
# $1: mount point
function assert_mount_point_in_fstab {
local _mount_point_match_regexp
_mount_point_match_regexp="$(get_mount_point_regexp "$1")"
grep "$_mount_point_match_regexp" -q /etc/fstab \
|| { echo "The mount point '$1' is not even in /etc/fstab, so we can't set up mount options" >&2; return 1; }
}
# $1: mount point
function remove_defaults_from_fstab_if_overriden {
local _mount_point_match_regexp
_mount_point_match_regexp="$(get_mount_point_regexp "$1")"
if [ $(grep "$_mount_point_match_regexp" /etc/fstab | grep -q "defaults,") -gt 0 ]
then
sed -i "s|\(${_mount_point_match_regexp}.*\)defaults,|\1|" /etc/fstab
fi
}
# $1: mount point
function ensure_partition_is_mounted {
local _mount_point="$1"
mkdir -p "$_mount_point" || return 1
if mountpoint -q "$_mount_point"; then
mount -o remount --target "$_mount_point"
else
mount --target "$_mount_point"
fi
}
include_mount_options_functions
# test "$mount_has_to_exist" = 'yes'
test "yes" = 'yes' && assert_mount_point_in_fstab /dev/shm \
|| { echo "Not remediating, because there is no record of /dev/shm in /etc/fstab" >&2; exit 1; }
ensure_mount_option_in_fstab "/dev/shm" "nosuid"
ensure_partition_is_mounted "/dev/shm"
Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | high |
---|
Strategy: | configure |
---|
- name: get back device associated to mountpoint
shell: mount | grep ' /dev/shm ' |cut -d ' ' -f 1
register: device_name
check_mode: no
tags:
- mount_option_dev_shm_nosuid
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: get back device previous mount option
shell: mount | grep ' /dev/shm ' | sed -re 's:.*\((.*)\):\1:'
register: device_cur_mountoption
check_mode: no
tags:
- mount_option_dev_shm_nosuid
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: get back device fstype
shell: mount | grep ' /dev/shm ' | cut -d ' ' -f 5
register: device_fstype
check_mode: no
tags:
- mount_option_dev_shm_nosuid
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: Ensure permission nosuid are set on /dev/shm
mount:
path: "/dev/shm"
src: "{{device_name.stdout}}"
opts: "{{device_cur_mountoption.stdout}},nosuid"
state: "mounted"
fstype: "{{device_fstype.stdout}}"
tags:
- mount_option_dev_shm_nosuid
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
Remediation Anaconda snippet: (show)
Complexity: | low |
---|
Disruption: | high |
---|
Strategy: | enable |
---|
part /dev/shm --mountoptions="nosuid"
|
Add nodev Option to /dev/shm
[ref]ruleThe nodev mount option can be used to prevent creation
of device files in /dev/shm .
Legitimate character and block devices should not exist
within temporary directories like /dev/shm .
Add the nodev option to the fourth column of
/etc/fstab for the line which controls mounting of
/dev/shm .
Rationale:The only legitimate location for device files is the /dev directory
located on the root partition. The only exception to this is chroot jails. Remediation Shell script: (show)
function include_mount_options_functions {
:
}
# $1: mount point
# $2: new mount point option
function ensure_mount_option_in_fstab {
local _mount_point="$1" _new_opt="$2" _mount_point_match_regexp="" _previous_mount_opts=""
_mount_point_match_regexp="$(get_mount_point_regexp "$_mount_point")"
if [ $(grep "$_mount_point_match_regexp" /etc/fstab | grep -c "$_new_opt" ) -eq 0 ]; then
_previous_mount_opts=$(grep "$_mount_point_match_regexp" /etc/fstab | awk '{print $4}')
sed -i "s|\(${_mount_point_match_regexp}.*${_previous_mount_opts}\)|\1,${_new_opt}|" /etc/fstab
fi
}
# $1: mount point
function get_mount_point_regexp {
printf "[[:space:]]%s[[:space:]]" "$1"
}
# $1: mount point
function assert_mount_point_in_fstab {
local _mount_point_match_regexp
_mount_point_match_regexp="$(get_mount_point_regexp "$1")"
grep "$_mount_point_match_regexp" -q /etc/fstab \
|| { echo "The mount point '$1' is not even in /etc/fstab, so we can't set up mount options" >&2; return 1; }
}
# $1: mount point
function remove_defaults_from_fstab_if_overriden {
local _mount_point_match_regexp
_mount_point_match_regexp="$(get_mount_point_regexp "$1")"
if [ $(grep "$_mount_point_match_regexp" /etc/fstab | grep -q "defaults,") -gt 0 ]
then
sed -i "s|\(${_mount_point_match_regexp}.*\)defaults,|\1|" /etc/fstab
fi
}
# $1: mount point
function ensure_partition_is_mounted {
local _mount_point="$1"
mkdir -p "$_mount_point" || return 1
if mountpoint -q "$_mount_point"; then
mount -o remount --target "$_mount_point"
else
mount --target "$_mount_point"
fi
}
include_mount_options_functions
# test "$mount_has_to_exist" = 'yes'
test "yes" = 'yes' && assert_mount_point_in_fstab /dev/shm \
|| { echo "Not remediating, because there is no record of /dev/shm in /etc/fstab" >&2; exit 1; }
ensure_mount_option_in_fstab "/dev/shm" "nodev"
ensure_partition_is_mounted "/dev/shm"
Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | high |
---|
Strategy: | configure |
---|
- name: get back device associated to mountpoint
shell: mount | grep ' /dev/shm ' |cut -d ' ' -f 1
register: device_name
check_mode: no
tags:
- mount_option_dev_shm_nodev
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: get back device previous mount option
shell: mount | grep ' /dev/shm ' | sed -re 's:.*\((.*)\):\1:'
register: device_cur_mountoption
check_mode: no
tags:
- mount_option_dev_shm_nodev
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: get back device fstype
shell: mount | grep ' /dev/shm ' | cut -d ' ' -f 5
register: device_fstype
check_mode: no
tags:
- mount_option_dev_shm_nodev
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
- name: Ensure permission nodev are set on /dev/shm
mount:
path: "/dev/shm"
src: "{{device_name.stdout}}"
opts: "{{device_cur_mountoption.stdout}},nodev"
state: "mounted"
fstype: "{{device_fstype.stdout}}"
tags:
- mount_option_dev_shm_nodev
- unknown_severity
- configure_strategy
- low_complexity
- high_disruption
- NIST-800-53-CM-7
- NIST-800-53-MP-2
Remediation Anaconda snippet: (show)
Complexity: | low |
---|
Disruption: | high |
---|
Strategy: | enable |
---|
part /dev/shm --mountoptions="nodev"
|
Installing and Maintaining Software
[ref]groupThe following sections contain information on
security-relevant choices during the initial operating system
installation process and the setup of software
updates. |
contains 4 rules |
SAP Specific Requirement
[ref]groupSAP (Systems, Applications and Products in Data Processing) is enterprise
software to manage business operations and customer relations. The
following section contains SAP specific requirement that is not part
of standard or common OS setting. |
|
System and Software Integrity
[ref]groupSystem and software integrity can be gained by installing antivirus, increasing
system encryption strength with FIPS, verifying installed software, enabling SELinux,
installing an Intrusion Prevention System, etc. However, installing or enabling integrity
checking tools cannot prevent intrusions, but they can detect that an intrusion
may have occurred. Requirements for integrity checking may be highly dependent on
the environment in which the system will be used. Snapshot-based approaches such
as AIDE may induce considerable overhead in the presence of frequent software updates. |
contains 2 rules |
Software Integrity Checking
[ref]groupBoth the AIDE (Advanced Intrusion Detection Environment)
software and the RPM package management system provide
mechanisms for verifying the integrity of installed software.
AIDE uses snapshots of file metadata (such as hashes) and compares these
to current system files in order to detect changes.
The RPM package management system can conduct integrity
checks by comparing information in its metadata database with
files installed on the system. |
contains 2 rules |
Verify Integrity with RPM
[ref]groupThe RPM package management system includes the ability
to verify the integrity of installed packages by comparing the
installed files with information about the files taken from the
package metadata stored in the RPM database. Although an attacker
could corrupt the RPM database (analogous to attacking the AIDE
database as described above), this check can still reveal
modification of important files. To list which files on the system differ from what is expected by the RPM database:
$ rpm -qVa
See the man page for rpm to see a complete explanation of each column. |
contains 2 rules |
Verify and Correct File Permissions with RPM
[ref]ruleThe RPM package management system can check file access permissions
of installed software packages, including many that are important
to system security.
Verify that the file permissions of system files
and commands match vendor values. Check the file permissions
with the following command:
$ sudo rpm -Va | grep '^.M'
Output indicates files that do not match vendor defaults.
After locating a file with incorrect permissions,
run the following command to determine which package owns it:
$ rpm -qf FILENAME
Next, run the following command to reset its permissions to
the correct values:
$ sudo rpm --setperms PACKAGENAME Rationale:Permissions on system binaries and configuration files that are too generous
could allow an unauthorized user to gain privileges that they should not have.
The permissions set by the vendor should be maintained. Any deviations from
this baseline should be investigated. References:
1.2.6, 6.1.3, 6.1.4, 6.1.5, 6.1.6, 6.1.7, 6.1.8, 6.1.9, 6.2.3, 5.10.4.1, 3.3.8, 3.4.1, CCI-001494, CCI-001496, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), AC-6, AU-9(1), AU-9(3), CM-6(d), CM-6(3), Req-11.5, SRG-OS-000257-GPOS-00098, SRG-OS-000278-GPOS-00108 Remediation Shell script: (show)
Complexity: | high |
---|
Disruption: | medium |
---|
Strategy: | restrict |
---|
# Declare array to hold list of RPM packages we need to correct permissions for
declare -a SETPERMS_RPM_LIST
# Create a list of files on the system having permissions different from what
# is expected by the RPM database
FILES_WITH_INCORRECT_PERMS=($(rpm -Va --nofiledigest | grep '^.M' | cut -d ' ' -f4-))
# For each file path from that list:
# * Determine the RPM package the file path is shipped by,
# * Include it into SETPERMS_RPM_LIST array
for FILE_PATH in "${FILES_WITH_INCORRECT_PERMS[@]}"
do
RPM_PACKAGE=$(rpm -qf "$FILE_PATH")
SETPERMS_RPM_LIST=("${SETPERMS_RPM_LIST[@]}" "$RPM_PACKAGE")
done
# Remove duplicate mention of same RPM in $SETPERMS_RPM_LIST (if any)
SETPERMS_RPM_LIST=( $(echo "${SETPERMS_RPM_LIST[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') )
# For each of the RPM packages left in the list -- reset its permissions to the
# correct values
for RPM_PACKAGE in "${SETPERMS_RPM_LIST[@]}"
do
rpm --setperms "${RPM_PACKAGE}"
done
|
Verify File Hashes with RPM
[ref]ruleWithout cryptographic integrity protections, system
executables and files can be altered by unauthorized users without
detection.
The RPM package management system can check the hashes of
installed software packages, including many that are important to system
security.
To verify that the cryptographic hash of system files and commands match vendor
values, run the following command to list which files on the system
have hashes that differ from what is expected by the RPM database:
$ rpm -Va | grep '^..5'
A "c" in the second column indicates that a file is a configuration file, which
may appropriately be expected to change. If the file was not expected to
change, investigate the cause of the change using audit logs or other means.
The package can then be reinstalled to restore the file.
Run the following command to determine which package owns the file:
$ rpm -qf FILENAME
The package can be reinstalled from a yum repository using the command:
$ sudo yum reinstall PACKAGENAME
Alternatively, the package can be reinstalled from trusted media using the command:
$ sudo rpm -Uvh PACKAGENAME Rationale:The hashes of important files like system executables should match the
information given by the RPM database. Executables with erroneous hashes could
be a sign of nefarious activity on the system. References:
1.2.6, 5.10.4.1, 3.3.8, 3.4.1, CCI-000663, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), CM-6(d), CM-6(3), SI-7(1), Req-11.5, SRG-OS-000480-GPOS-00227 Remediation Ansible snippet: (show)
Complexity: | high |
---|
Disruption: | medium |
---|
- name: "Set fact: Package manager reinstall command (dnf)"
set_fact:
package_manager_reinstall_cmd: dnf reinstall -y
when: ansible_distribution == "Fedora"
tags:
- rpm_verify_hashes
- high_severity
- unknown_strategy
- high_complexity
- medium_disruption
- NIST-800-53-CM-6(d)
- NIST-800-53-CM-6(3)
- NIST-800-53-SI-7(1)
- NIST-800-171-3.3.8
- NIST-800-171-3.4.1
- PCI-DSS-Req-11.5
- CJIS-5.10.4.1
- name: "Set fact: Package manager reinstall command (yum)"
set_fact:
package_manager_reinstall_cmd: yum reinstall -y
when: ansible_distribution == "RedHat" or ansible_distribution == "OracleLinux"
tags:
- rpm_verify_hashes
- high_severity
- unknown_strategy
- high_complexity
- medium_disruption
- NIST-800-53-CM-6(d)
- NIST-800-53-CM-6(3)
- NIST-800-53-SI-7(1)
- NIST-800-171-3.3.8
- NIST-800-171-3.4.1
- PCI-DSS-Req-11.5
- CJIS-5.10.4.1
- name: "Read files with incorrect hash"
shell: "rpm -Va | grep -E '^..5.* /(bin|sbin|lib|lib64|usr)/' | sed -r 's;^.*\\s+(.+);\\1;g'"
register: files_with_incorrect_hash
changed_when: False
when: package_manager_reinstall_cmd is defined
check_mode: no
tags:
- rpm_verify_hashes
- high_severity
- unknown_strategy
- high_complexity
- medium_disruption
- NIST-800-53-CM-6(d)
- NIST-800-53-CM-6(3)
- NIST-800-53-SI-7(1)
- NIST-800-171-3.3.8
- NIST-800-171-3.4.1
- PCI-DSS-Req-11.5
- CJIS-5.10.4.1
- name: "Reinstall packages of files with incorrect hash"
shell: "{{package_manager_reinstall_cmd}} $(rpm -qf '{{item}}')"
with_items: "{{ files_with_incorrect_hash.stdout_lines }}"
when: package_manager_reinstall_cmd is defined and (files_with_incorrect_hash.stdout_lines | length > 0)
tags:
- rpm_verify_hashes
- high_severity
- unknown_strategy
- high_complexity
- medium_disruption
- NIST-800-53-CM-6(d)
- NIST-800-53-CM-6(3)
- NIST-800-53-SI-7(1)
- NIST-800-171-3.3.8
- NIST-800-171-3.4.1
- PCI-DSS-Req-11.5
- CJIS-5.10.4.1
|
Updating Software
[ref]groupThe yum command line tool is used to install and
update software packages. The system also provides a graphical
software update tool in the System menu, in the Administration submenu,
called Software Update.
Red Hat Enterprise Linux systems contain an installed software catalog called
the RPM database, which records metadata of installed packages. Consistently using
yum or the graphical Software Update for all software installation
allows for insight into the current inventory of installed software on the system.
Oracle Linux system contain an installed software catalog called
the RPM database, which records metadata of installed packages. Consistently using
yum or the graphical Software Update for all software installation
allows for insight into the current inventory of installed software on the system. |
contains 2 rules |
Ensure Oracle Linux GPG Key Installed
[ref]ruleTo ensure the system can cryptographically verify base software
packages come from Oracle (and to connect to the Unbreakable Linux Network to
receive them), the Oracle GPG key must properly be installed.
To install the Oracle GPG key, run:
$ sudo uln_register
If the system is not connected to the Internet,
then install the Oracle GPG key from trusted media such as
the Oracle installation CD-ROM or DVD. Assuming the disc is mounted
in /media/cdrom , use the following command as the root user to import
it into the keyring:
$ sudo rpm --import /media/cdrom/RPM-GPG-KEY Rationale:Changes to software components can have significant effects on the
overall security of the operating system. This requirement ensures
the software has not been tampered with and that it has been provided
by a trusted vendor. The Oracle GPG key is necessary to
cryptographically verify packages are from Oracle. Remediation Shell script: (show)
# OL fingerprints below retrieved from "Oracle Linux Unbreakable Linux Network User's Guide"
# https://docs.oracle.com/cd/E37670_01/E39381/html/ol_import_gpg.html
readonly OL_FINGERPRINT="4214 4123 FECF C55B 9086 313D 72F9 7B74 EC55 1F03"
# Location of the key we would like to import (once it's integrity verified)
readonly OL_RELEASE_KEY="/etc/pki/rpm-gpg/RPM-GPG-KEY-oracle"
RPM_GPG_DIR_PERMS=$(stat -c %a "$(dirname "$OL_RELEASE_KEY")")
# Verify /etc/pki/rpm-gpg directory permissions are safe
if [ "${RPM_GPG_DIR_PERMS}" -le "755" ]
then
# If they are safe, try to obtain fingerprints from the key file
# (to ensure there won't be e.g. CRC error)
IFS=$'\n' GPG_OUT=($(gpg --with-fingerprint "${OL_RELEASE_KEY}"))
GPG_RESULT=$?
# No CRC error, safe to proceed
if [ "${GPG_RESULT}" -eq "0" ]
then
for ITEM in "${GPG_OUT[@]}"
do
# Filter just hexadecimal fingerprints from gpg's output from
# processing of a key file
RESULT=$(echo ${ITEM} | sed -n "s/[[:space:]]*Key fingerprint = \(.*\)/\1/p" | tr -s '[:space:]')
# If fingerprint matches Oracle Linux 6 and 7 key import the key
if [[ ${RESULT} ]] && [[ ${RESULT} = "${OL_FINGERPRINT}" ]]
then
rpm --import "${OL_RELEASE_KEY}"
fi
done
fi
fi
|
Ensure gpgcheck Enabled In Main Yum Configuration
[ref]ruleThe gpgcheck option controls whether
RPM packages' signatures are always checked prior to installation.
To configure yum to check package signatures before installing
them, ensure the following line appears in /etc/yum.conf in
the [main] section:
gpgcheck=1 Rationale:Changes to any software components can have significant effects on the overall security
of the operating system. This requirement ensures the software has not been tampered with
and that it has been provided by a trusted vendor.
Accordingly, patches, service packs, device drivers, or operating system components must
be signed with a certificate recognized and approved by the organization.
Verifying the authenticity of the software prior to installation
validates the integrity of the patch or upgrade received from
a vendor. This ensures the software has not been tampered with and
that it has been provided by a trusted vendor. Self-signed
certificates are disallowed by this requirement. Certificates
used to verify the software must be from an approved Certificate
Authority (CA). References:
1.2.2, 5.10.4.1, 3.4.8, CCI-001749, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), CM-5(3), SI-7, MA-1(b), Req-6.2, SRG-OS-000366-GPOS-00153 Remediation Shell script: (show)
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file: Configuration file that will be modified
# key: Configuration option to change
# value: Value of the configuration option to change
# cce: The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format: The printf-like format string that will be given stripped key and value as arguments,
# so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format: Optional argument to specify the format of how key/value should be
# modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
# With default format of 'key = value':
# replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
# With custom key/value format:
# replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
# With a variable:
# replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
local config_file=$1
local key=$2
local value=$3
local cce=$4
local format=$5
if [ "$case_insensitive_mode" = yes ]; then
sed_case_insensitive_option="i"
grep_case_insensitive_option="-i"
fi
[ -n "$format" ] || format="$default_format"
# Check sanity of the input
[ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }
# Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
# Otherwise, regular sed command will do.
sed_command=('sed' '-i')
if test -L "$config_file"; then
sed_command+=('--follow-symlinks')
fi
# Test that the cce arg is not empty or does not equal @CCENUM@.
# If @CCENUM@ exists, it means that there is no CCE assigned.
if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
cce="CCE-${cce}"
else
cce="CCE"
fi
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")
# shellcheck disable=SC2059
printf -v formatted_output "$format" "$stripped_key" "$value"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if grep -q $grep_case_insensitive_option "${key}\\>" "$config_file"; then
"${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
else
# \n is precaution for case where file ends without trailing newline
printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
printf '%s\n' "$formatted_output" >> "$config_file"
fi
}
replace_or_append '/etc/yum.conf' '^gpgcheck' '1' ''
|