Guide to the Secure Configuration of Red Hat Enterprise Linux 7

with profile C2S for Red Hat Enterprise Linux 7
This profile demonstrates compliance against the U.S. Government Commercial Cloud Services (C2S) baseline. This baseline was inspired by the Center for Internet Security (CIS) Red Hat Enterprise Linux 7 Benchmark, v2.1.1 - 01-31-2017. For the SCAP Security Guide project to remain in compliance with CIS' terms and conditions, specifically Restrictions(8), note there is no representation or claim that the C2S profile will ensure a system is in compliance or consistency with the CIS baseline.

This guide presents a catalog of security-relevant configuration settings for Red Hat Enterprise Linux 7. It is a rendering of content structured in the eXtensible Configuration Checklist Description Format (XCCDF) in order to support security automation. The SCAP content is is available in the scap-security-guide package which is developed at https://www.open-scap.org/security-policies/scap-security-guide.

Providing system administrators with such guidance informs them how to securely configure systems under their control in a variety of network roles. Policy makers and baseline creators can use this catalog of settings, with its associated references to higher-level security control catalogs, in order to assist them in security baseline creation. This guide is a catalog, not a checklist, and satisfaction of every item is not likely to be possible or sensible in many operational scenarios. However, the XCCDF format enables granular selection and adjustment of settings, and their association with OVAL and OCIL content provides an automated checking capability. Transformations of this document, and its associated automated checking content, are capable of providing baselines that meet a diverse set of policy objectives. Some example XCCDF Profiles, which are selections of items that form checklists and can be used as baselines, are available with this guide. They can be processed, in an automated fashion, with tools that support the Security Content Automation Protocol (SCAP). The DISA STIG for Red Hat Enterprise Linux 7, which provides required settings for US Department of Defense systems, is one example of a baseline created from this guidance.
Do not attempt to implement any of the settings in this guide without first testing them in a non-operational environment. The creators of this guidance assume no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic.
Profile TitleC2S for Red Hat Enterprise Linux 7
Profile IDxccdf_org.ssgproject.content_profile_C2S

Revision History

Current version: 0.1.36

  • draft (as of 2017-08-29)

Platforms

  • cpe:/o:redhat:enterprise_linux:7
  • cpe:/o:redhat:enterprise_linux:7::client
  • cpe:/o:redhat:enterprise_linux:7::computenode

Table of Contents

  1. System Settings
    1. Installing and Maintaining Software
    2. File Permissions and Masks
    3. SELinux
    4. Account and Access Control
    5. Network Configuration and Firewalls
    6. Configure Syslog
    7. System Accounting with auditd
  2. Services
    1. Base Services
    2. Cron and At Daemons
    3. SSH Server

Checklist

contains 68 rules

System Settings   [ref]group

Contains rules that check correct system settings.

contains 58 rules

Installing and Maintaining Software   [ref]group

The following sections contain information on security-relevant choices during the initial operating system installation process and the setup of software updates.

contains 10 rules

Disk Partitioning   [ref]group

To ensure separation and protection of data, there are top-level system directories which should be placed on their own physical partition or logical volume. The installer's default partitioning scheme creates separate logical volumes for /, /boot, and swap.

  • If starting with any of the default layouts, check the box to "Review and modify partitioning." This allows for the easy creation of additional logical volumes inside the volume group already created, though it may require making /'s logical volume smaller to create space. In general, using logical volumes is preferable to using partitions because they can be more easily adjusted later.
  • If creating a custom layout, create the partitions mentioned in the previous paragraph (which the installer will require anyway), as well as separate ones described in the following sections.
If a system has already been installed, and the default partitioning scheme was used, it is possible but nontrivial to modify it to create separate logical volumes for the directories listed above. The Logical Volume Manager (LVM) makes this possible. See the LVM HOWTO at http://tldp.org/HOWTO/LVM-HOWTO/ for more detailed information on LVM.

contains 5 rules

Ensure /tmp Located On Separate Partition   [ref]rule

The /tmp directory is a world-writable directory used for temporary file storage. Ensure it has its own partition or logical volume at installation time, or migrate it using LVM.

Rationale:

The /tmp partition is used as temporary storage by many programs. Placing /tmp in its own partition enables the setting of more restrictive mount options, which can help protect programs which use it.

Severity:  low

Identifiers:  CCE-27173-4

References:  RHEL-07-021340, SC-32(1), 366, SRG-OS-000480-GPOS-00227, 1.1.2

Ensure /var Located On Separate Partition   [ref]rule

The /var directory is used by daemons and other system services to store frequently-changing data. Ensure that /var has its own partition or logical volume at installation time, or migrate it using LVM.

Rationale:

Ensuring that /var is mounted on its own partition enables the setting of more restrictive mount options. This helps protect system services such as daemons or other programs which use it. It is not uncommon for the /var directory to contain world-writable directories installed by other software packages.

Severity:  low

Identifiers:  CCE-26404-4

References:  RHEL-07-021320, SC-32(1), 1.1.6, 366, SRG-OS-000480-GPOS-00227

Ensure /var/log Located On Separate Partition   [ref]rule

System logs are stored in the /var/log directory. Ensure that it has its own partition or logical volume at installation time, or migrate it using LVM.

Rationale:

Placing /var/log in its own partition enables better separation between log files and other files in /var/.

Severity:  low

Identifiers:  CCE-26967-0

References:  AU-9, SC-32, http://iase.disa.mil/stigs/cci/Pages/index.aspx, 1.1.11

Ensure /var/log/audit Located On Separate Partition   [ref]rule

Audit logs are stored in the /var/log/audit directory. Ensure that it has its own partition or logical volume at installation time, or migrate it later using LVM. Make absolutely certain that it is large enough to store all audit logs that will be created by the auditing daemon.

Rationale:

Placing /var/log/audit in its own partition enables better separation between audit files and other files, and helps ensure that auditing cannot be halted due to the partition running out of space.

Severity:  low

Identifiers:  CCE-26971-2

References:  RHEL-07-021330, AU-4, AU-9, SC-32(1), 366, 1.1.12, SRG-OS-000480-GPOS-00227

Ensure /home Located On Separate Partition   [ref]rule

If user home directories will be stored locally, create a separate partition for /home at installation time (or migrate it later using LVM). If /home will be mounted from another system such as an NFS server, then creating a separate partition is not necessary at installation time, and the mountpoint can instead be configured later.

Rationale:

Ensuring that /home is mounted on its own partition enables the setting of more restrictive mount options, and also helps ensure that users cannot trivially fill partitions used for log or audit data storage.

Severity:  low

Identifiers:  CCE-80144-9

References:  RHEL-07-021310, SC-32(1), 366, 1208, 1.1.13, SRG-OS-000480-GPOS-00227

Updating Software   [ref]group

The 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.

contains 2 rules

Ensure Red Hat GPG Key Installed   [ref]rule

To ensure the system can cryptographically verify base software packages come from Red Hat (and to connect to the Red Hat Network to receive them), the Red Hat GPG key must properly be installed. To install the Red Hat GPG key, run:

$ sudo subscription-manager register
If the system is not connected to the Internet or an RHN Satellite, then install the Red Hat GPG key from trusted media such as the Red Hat 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 Red Hat GPG key is necessary to cryptographically verify packages are from Red Hat.

Severity:  high

Identifiers:  CCE-26957-1

References:  CM-5(3), SI-7, MA-1(b), 1749, 366, Req-6.2, 1.2.3, 5.10.4.1, 3.4.8

Remediation Shell script:   (show)

# The two fingerprints below are retrieved from https://access.redhat.com/security/team/key
readonly REDHAT_RELEASE_2_FINGERPRINT="567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51"
readonly REDHAT_AUXILIARY_FINGERPRINT="43A6 E49C 4A38 F4BE 9ABF 2A53 4568 9C88 2FA6 58E0"
# Location of the key we would like to import (once it's integrity verified)
readonly REDHAT_RELEASE_KEY="/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"

RPM_GPG_DIR_PERMS=$(stat -c %a "$(dirname "$REDHAT_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 "${REDHAT_RELEASE_KEY}" | grep 'Key fingerprint ='))
  GPG_RESULT=$?
  # No CRC error, safe to proceed
  if [ "${GPG_RESULT}" -eq "0" ]
  then
    tr -s ' ' <<< "${GPG_OUT}" | grep -vE "${REDHAT_RELEASE_2_FINGERPRINT}|${REDHAT_AUXILIARY_FINGERPRINT}" || {
      # If file doesn't contains any keys with unknown fingerprint, import it
      rpm --import "${REDHAT_RELEASE_KEY}"
    }
  fi
fi
Remediation Ansible snippet:   (show)

Complexity:medium
Disruption:medium
Strategy:restrict
- name: "Read permission of GPG key directory"
  stat:
    path: /etc/pki/rpm-gpg/
  register: gpg_key_directory_permission
  check_mode: no
  tags:
    - ensure_redhat_gpgkey_installed
    - high_severity
    - restrict_strategy
    - medium_complexity
    - medium_disruption
    - CCE-26957-1
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

# It should fail if it doesn't find any fingerprints in file - maybe file was not parsed well.

- name: Read signatures in GPG key
  shell: gpg --with-fingerprint '/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release' | grep 'Key fingerprint =' | tr -s ' ' | sed 's;.*= ;;g'
  changed_when: False
  register: gpg_fingerprints
  check_mode: no
  tags:
    - ensure_redhat_gpgkey_installed
    - high_severity
    - restrict_strategy
    - medium_complexity
    - medium_disruption
    - CCE-26957-1
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

- name: Set Fact - Valid fingerprints
  set_fact:
     gpg_valid_fingerprints: ("567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51" "43A6 E49C 4A38 F4BE 9ABF 2A53 4568 9C88 2FA6 58E0")
  tags:
    - ensure_redhat_gpgkey_installed
    - high_severity
    - restrict_strategy
    - medium_complexity
    - medium_disruption
    - CCE-26957-1
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

- name: Import RedHat GPG key
  rpm_key:
    state: present
    key: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
  when:
    (gpg_key_directory_permission.stat.mode <= '0755')
    and (( gpg_fingerprints.stdout_lines | difference(gpg_valid_fingerprints)) | length == 0)
    and (gpg_fingerprints.stdout_lines | length > 0)
    and (ansible_distribution == "RedHat")
  tags:
    - ensure_redhat_gpgkey_installed
    - high_severity
    - restrict_strategy
    - medium_complexity
    - medium_disruption
    - CCE-26957-1
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

Ensure gpgcheck Enabled In Main Yum Configuration   [ref]rule

The 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).

Severity:  high

Identifiers:  CCE-26989-4

References:  RHEL-07-020050, CM-5(3), SI-7, MA-1(b), 1749, SRG-OS-000366-GPOS-00153, Req-6.2, 1.2.2, 5.10.4.1, 3.4.8

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/yum.conf' '^gpgcheck' '1' 'CCE-26989-4'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
- name: "Check existence of yum on Fedora"
  stat:
    path: /etc/yum.conf
  register: yum_config_file
  check_mode: no
  when: ansible_distribution == "Fedora"

# Old versions of Fedora use yum

- name: "Ensure GPG check is globally activated (yum)"
  ini_file:
    dest: "{{item}}"
    section: main
    option: gpgcheck
    value: 1
    create: False
  with_items: "/etc/yum.conf"
  when: ansible_distribution == "RedHat" or yum_config_file.stat.exists
  tags:
    - ensure_gpgcheck_globally_activated
    - high_severity
    - unknown_strategy
    - low_complexity
    - medium_disruption
    - CCE-26989-4
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

- name: "Ensure GPG check is globally activated (dnf)"
  ini_file:
    dest: "{{item}}"
    section: main
    option: gpgcheck
    value: 1
    create: False
  with_items: "/etc/dnf/dnf.conf"
  when: ansible_distribution == "Fedora"
  tags:
    - ensure_gpgcheck_globally_activated
    - high_severity
    - unknown_strategy
    - low_complexity
    - medium_disruption
    - CCE-26989-4
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-MA-1(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

System and Software Integrity   [ref]group

System 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 3 rules

Software Integrity Checking   [ref]group

Both 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 AIDE   [ref]group

AIDE conducts integrity checks by comparing information about files with previously-gathered information. Ideally, the AIDE database is created immediately after initial system configuration, and then again after any software update. AIDE is highly configurable, with further configuration information located in /usr/share/doc/aide-VERSION.

contains 2 rules

Install AIDE   [ref]rule

Install the AIDE package with the command:

$ sudo yum install aide

Rationale:

The AIDE package must be installed if it is to be available for integrity checking.

Severity:  medium

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:enable
# Function to install or uninstall packages on RHEL and Fedora systems.
#
# Example Call(s):
#
#     package_command install aide
#     package_command remove telnet-server
#
function package_command {

# Load function arguments into local variables
local package_operation=$1
local package=$2

# Check sanity of the input
if [ $# -ne "2" ]
then
  echo "Usage: package_command 'install/uninstall' 'rpm_package_name"
  echo "Aborting."
  exit 1
fi

# If dnf is installed, use dnf; otherwise, use yum
if [ -f "/usr/bin/dnf" ] ; then
  install_util="/usr/bin/dnf"
else
  install_util="/usr/bin/yum"
fi

if [ "$package_operation" != 'remove' ] ; then
  # If the rpm is not installed, install the rpm
  if ! /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
else
  # If the rpm is installed, uninstall the rpm
  if /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
fi

}

package_command install aide
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
- name: "Ensure aide is installed"
  package:
    name="{{item}}"
    state=present
  with_items:
    - aide
  tags:
    - package_aide_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - CCE-27096-7
    - NIST-800-53-CM-3(d)
    - NIST-800-53-CM-3(e)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-CM-6(3)
    - NIST-800-53-SC-28
    - NIST-800-53-SI-7
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3

Remediation Puppet snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
include install_aide

class install_aide {
  package { 'aide':
    ensure => 'installed',
  }
}
Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable

package --add=aide

Configure Periodic Execution of AIDE   [ref]rule

At a minimum, AIDE should be configured to run a weekly scan. At most, AIDE should be run daily. To implement a daily execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:

05 4 * * * root /usr/sbin/aide --check
To implement a weekly execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:
05 4 * * 0 root /usr/sbin/aide --check
AIDE can be executed periodically through other means; this is merely one example.

Rationale:

By default, AIDE does not install itself for periodic execution. Periodically running AIDE is necessary to reveal unexpected changes in installed files.

Unauthorized changes to the baseline configuration could make the system vulnerable to various attacks or allow unauthorized access to the operating system. Changes to operating system configurations can have unintended side effects, some of which may be relevant to security.

Detecting such changes and providing an automated response can help avoid unintended, negative consequences that could ultimately affect the security state of the operating system. The operating system's Information Management Officer (IMO)/Information System Security Officer (ISSO) and System Administrators (SAs) must be notified via email and/or monitoring system trap when there is an unauthorized modification of a configuration item.

Severity:  medium

Remediation Shell script:   (show)

# Function to install or uninstall packages on RHEL and Fedora systems.
#
# Example Call(s):
#
#     package_command install aide
#     package_command remove telnet-server
#
function package_command {

# Load function arguments into local variables
local package_operation=$1
local package=$2

# Check sanity of the input
if [ $# -ne "2" ]
then
  echo "Usage: package_command 'install/uninstall' 'rpm_package_name"
  echo "Aborting."
  exit 1
fi

# If dnf is installed, use dnf; otherwise, use yum
if [ -f "/usr/bin/dnf" ] ; then
  install_util="/usr/bin/dnf"
else
  install_util="/usr/bin/yum"
fi

if [ "$package_operation" != 'remove' ] ; then
  # If the rpm is not installed, install the rpm
  if ! /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
else
  # If the rpm is installed, uninstall the rpm
  if /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
fi

}

package_command install aide

if ! grep -q "/usr/sbin/aide --check" /etc/crontab ; then
    echo "05 4 * * * root /usr/sbin/aide --check" >> /etc/crontab
fi

File Permissions and Masks   [ref]group

Traditional 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 21 rules

Restrict Partition Mount Options   [ref]group

System 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 9 rules

Add nodev Option to Removable Media Partitions   [ref]rule

The nodev mount option prevents files from being interpreted as character or block devices. Legitimate character and block devices should exist only in the /dev directory on the root partition or within chroot jails built for system services. Add the nodev option to the fourth column of /etc/fstab for the line which controls mounting of any removable media partitions.

Rationale:

The only legitimate location for device files is the /dev directory located on the root partition. An exception to this is chroot jails, and it is not advised to set nodev on partitions which contain their root filesystems.

Severity:  low

Identifiers:  CCE-80146-4

References:  AC-19(a), AC-19(d), AC-19(e), CM-7, MP-2, 1.1.18

Remediation Shell script:   (show)


var_removable_partition="(N/A)"

NEW_OPT="nodev"

if [ $(grep "$var_removable_partition" /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
  MNT_OPTS=$(grep "$var_removable_partition" /etc/fstab | awk '{print $4}')
  sed -i "s|\($var_removable_partition.*${MNT_OPTS}\)|\1,${NEW_OPT}|" /etc/fstab
fi

Add noexec Option to Removable Media Partitions   [ref]rule

The noexec mount option prevents the direct execution of binaries on the mounted filesystem. Preventing the direct execution of binaries from removable media (such as a USB key) provides a defense against malicious software that may be present on such untrusted media. Add the noexec option to the fourth column of /etc/fstab for the line which controls mounting of any removable media partitions.

Rationale:

Allowing users to execute binaries from removable media such as USB keys exposes the system to potential compromise.

Severity:  low

Identifiers:  CCE-80147-2

References:  AC-19(a), AC-19(d), AC-19(e), CM-7, MP-2, 87, 1.1.20

Remediation Shell script:   (show)


var_removable_partition="(N/A)"

NEW_OPT="noexec"

if [ $(grep "$var_removable_partition" /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
  MNT_OPTS=$(grep "$var_removable_partition" /etc/fstab | awk '{print $4}')
  sed -i "s|\($var_removable_partition.*${MNT_OPTS}\)|\1,${NEW_OPT}|" /etc/fstab
fi

Add nosuid Option to Removable Media Partitions   [ref]rule

The nosuid mount option prevents set-user-identifier (SUID) and set-group-identifier (SGID) permissions from taking effect. These permissions allow users to execute binaries with the same permissions as the owner and group of the file respectively. Users should not be allowed to introduce SUID and SGID files into the system via partitions mounted from removeable media. Add the nosuid option to the fourth column of /etc/fstab for the line which controls mounting of any removable media partitions.

Rationale:

The presence of SUID and SGID executables should be tightly controlled. Allowing users to introduce SUID or SGID binaries from partitions mounted off of removable media would allow them to introduce their own highly-privileged programs.

Severity:  low

Identifiers:  CCE-80148-0

References:  RHEL-07-021010, AC-6, AC-19(a), AC-19(d), AC-19(e), CM-7, MP-2, 1.1.19, 366, SRG-OS-000480-GPOS-00227

Remediation Shell script:   (show)


var_removable_partition="(N/A)"

NEW_OPT="nosuid"

if [ $(grep "$var_removable_partition" /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
  MNT_OPTS=$(grep "$var_removable_partition" /etc/fstab | awk '{print $4}')
  sed -i "s|\($var_removable_partition.*${MNT_OPTS}\)|\1,${NEW_OPT}|" /etc/fstab
fi

Add nodev Option to /tmp   [ref]rule

The nodev mount option can be used to prevent device files from being created in /tmp. Legitimate character and block devices should not exist within temporary directories like /tmp. Add the nodev option to the fourth column of /etc/fstab for the line which controls mounting of /tmp.

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.

Severity:  low

Identifiers:  CCE-80149-8

References:  CM-7, MP-2, 1.1.3

Remediation Shell script:   (show)

NEW_OPT=nodev

if [ $(grep " \/tmp " /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
        MNT_OPTS=$(grep " \/tmp " /etc/fstab | awk '{print $4}')
        sed -i "s/\( \/tmp.*${MNT_OPTS}\)/\1,${NEW_OPT}/" /etc/fstab
        
        if [ $MNT_OPTS = "defaults" ]
        then
                sed -i "s/defaults,//" /etc/fstab
        fi
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:high
Strategy:configure
- name: "get back device associated to mountpoint"
  shell: mount | grep ' /tmp ' |cut -d ' ' -f 1
  register: device_name
  check_mode: no
  tags:
    - mount_option_tmp_nodev
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80149-8
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device previous mount option"
  shell: mount | grep ' /tmp ' | sed -re 's:.*\((.*)\):\1:'
  register: device_cur_mountoption
  check_mode: no
  tags:
    - mount_option_tmp_nodev
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80149-8
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device fstype"
  shell: mount | grep ' /tmp ' | cut -d ' ' -f 5
  register: device_fstype
  check_mode: no
  tags:
    - mount_option_tmp_nodev
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80149-8
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "Ensure permission nodev are set on /tmp"
  mount:
    path: "/tmp"
    src: "{{device_name.stdout}}"
    opts: "{{device_cur_mountoption.stdout}},nodev"
    state: "mounted"
    fstype: "{{device_fstype.stdout}}"
  tags:
    - mount_option_tmp_nodev
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80149-8
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:high
Strategy:enable

part /tmp --mountoptions="nodev"

Add noexec Option to /tmp   [ref]rule

The noexec mount option can be used to prevent binaries from being executed out of /tmp. Add the noexec option to the fourth column of /etc/fstab for the line which controls mounting of /tmp.

Rationale:

Allowing users to execute binaries from world-writable directories such as /tmp should never be necessary in normal operation and can expose the system to potential compromise.

Severity:  low

Identifiers:  CCE-80150-6

References:  CM-7, MP-2, 1.1.4

Remediation Shell script:   (show)

NEW_OPT=noexec

if [ $(grep " \/tmp " /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
        MNT_OPTS=$(grep " \/tmp " /etc/fstab | awk '{print $4}')
        sed -i "s/\( \/tmp.*${MNT_OPTS}\)/\1,${NEW_OPT}/" /etc/fstab
        
        if [ $MNT_OPTS = "defaults" ]
        then
                sed -i "s/defaults,//" /etc/fstab
        fi
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:high
Strategy:configure
- name: "get back device associated to mountpoint"
  shell: mount | grep ' /tmp ' |cut -d ' ' -f 1
  register: device_name
  check_mode: no
  tags:
    - mount_option_tmp_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80150-6
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device previous mount option"
  shell: mount | grep ' /tmp ' | sed -re 's:.*\((.*)\):\1:'
  register: device_cur_mountoption
  check_mode: no
  tags:
    - mount_option_tmp_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80150-6
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device fstype"
  shell: mount | grep ' /tmp ' | cut -d ' ' -f 5
  register: device_fstype
  check_mode: no
  tags:
    - mount_option_tmp_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80150-6
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "Ensure permission noexec are set on /tmp"
  mount:
    path: "/tmp"
    src: "{{device_name.stdout}}"
    opts: "{{device_cur_mountoption.stdout}},noexec"
    state: "mounted"
    fstype: "{{device_fstype.stdout}}"
  tags:
    - mount_option_tmp_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80150-6
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:high
Strategy:enable

part /tmp --mountoptions="noexec"

Add nosuid Option to /tmp   [ref]rule

The nosuid mount option can be used to prevent execution of setuid programs in /tmp. 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 /tmp.

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.

Severity:  low

Identifiers:  CCE-80151-4

References:  CM-7, MP-2, 1.1.4

Remediation Shell script:   (show)

NEW_OPT="nosuid"

if [ $(grep " \/tmp " /etc/fstab | grep -c "$NEW_OPT" ) -eq 0 ]; then
        MNT_OPTS=$(grep " \/tmp " /etc/fstab | awk '{print $4}')
        sed -i "s/\( \/tmp.*${MNT_OPTS}\)/\1,${NEW_OPT}/" /etc/fstab
        
        if [ $MNT_OPTS = "defaults" ]
        then
        	sed -i "s/defaults,//" /etc/fstab
        fi
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:high
Strategy:configure
- name: "get back device associated to mountpoint"
  shell: mount | grep ' /tmp ' |cut -d ' ' -f 1
  register: device_name
  check_mode: no
  tags:
    - mount_option_tmp_nosuid
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80151-4
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device previous mount option"
  shell: mount | grep ' /tmp ' | sed -re 's:.*\((.*)\):\1:'
  register: device_cur_mountoption
  check_mode: no
  tags:
    - mount_option_tmp_nosuid
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80151-4
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "get back device fstype"
  shell: mount | grep ' /tmp ' | cut -d ' ' -f 5
  register: device_fstype
  check_mode: no
  tags:
    - mount_option_tmp_nosuid
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80151-4
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "Ensure permission nosuid are set on /tmp"
  mount:
    path: "/tmp"
    src: "{{device_name.stdout}}"
    opts: "{{device_cur_mountoption.stdout}},nosuid"
    state: "mounted"
    fstype: "{{device_fstype.stdout}}"
  tags:
    - mount_option_tmp_nosuid
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80151-4
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:high
Strategy:enable

part /tmp --mountoptions="nosuid"

Add nodev Option to /dev/shm   [ref]rule

The 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.

Severity:  low

Identifiers:  CCE-80152-2

References:  CM-7, MP-2, 1.1.15

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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80152-2
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80152-2
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80152-2
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80152-2
    - 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"

Add noexec Option to /dev/shm   [ref]rule

The noexec mount option can be used to prevent binaries from being executed out of /dev/shm. It can be dangerous to allow the execution of binaries from world-writable temporary storage directories such as /dev/shm. Add the noexec option to the fourth column of /etc/fstab for the line which controls mounting of /dev/shm.

Rationale:

Allowing users to execute binaries from world-writable directories such as /dev/shm can expose the system to potential compromise.

Severity:  low

Identifiers:  CCE-80153-0

References:  CM-7, MP-2, 1.1.17

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_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80153-0
    - 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_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80153-0
    - 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_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80153-0
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

- name: "Ensure permission noexec are set on /dev/shm"
  mount:
    path: "/dev/shm"
    src: "{{device_name.stdout}}"
    opts: "{{device_cur_mountoption.stdout}},noexec"
    state: "mounted"
    fstype: "{{device_fstype.stdout}}"
  tags:
    - mount_option_dev_shm_noexec
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80153-0
    - NIST-800-53-CM-7
    - NIST-800-53-MP-2

Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:high
Strategy:enable

part /dev/shm --mountoptions="noexec"

Add nosuid Option to /dev/shm   [ref]rule

The 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.

Severity:  low

Identifiers:  CCE-80154-8

References:  CM-7, MP-2, 1.1.16

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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80154-8
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80154-8
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80154-8
    - 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
    - low_severity
    - configure_strategy
    - low_complexity
    - high_disruption
    - CCE-80154-8
    - 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"

Restrict Dynamic Mounting and Unmounting of Filesystems   [ref]group

Linux includes a number of facilities for the automated addition and removal of filesystems on a running system. These facilities may be necessary in many environments, but this capability also carries some risk -- whether direct risk from allowing users to introduce arbitrary filesystems, or risk that software flaws in the automated mount facility itself could allow an attacker to compromise the system.

This command can be used to list the types of filesystems that are available to the currently executing kernel:

$ find /lib/modules/`uname -r`/kernel/fs -type f -name '*.ko'
If these filesystems are not required then they can be explicitly disabled in a configuratio file in /etc/modprobe.d.

contains 7 rules

Disable Mounting of cramfs   [ref]rule

To configure the system to prevent the cramfs kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install cramfs /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80137-3

References:  CM-7, 1.1.1.1, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install cramfs" /etc/modprobe.d/cramfs.conf ; then
	sed -i 's/^install cramfs.*/install cramfs /bin/true/g' /etc/modprobe.d/cramfs.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/cramfs.conf
	echo "install cramfs /bin/true" >> /etc/modprobe.d/cramfs.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'cramfs' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - cramfs
  tags:
    - kernel_module_cramfs_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80137-3
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of freevxfs   [ref]rule

To configure the system to prevent the freevxfs kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install freevxfs /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80138-1

References:  CM-7, 1.1.1.2, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install freevxfs" /etc/modprobe.d/freevxfs.conf ; then
	sed -i 's/^install freevxfs.*/install freevxfs /bin/true/g' /etc/modprobe.d/freevxfs.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/freevxfs.conf
	echo "install freevxfs /bin/true" >> /etc/modprobe.d/freevxfs.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'freevxfs' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - freevxfs
  tags:
    - kernel_module_freevxfs_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80138-1
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of jffs2   [ref]rule

To configure the system to prevent the jffs2 kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install jffs2 /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80139-9

References:  CM-7, 1.1.1.3, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install jffs2" /etc/modprobe.d/jffs2.conf ; then
	sed -i 's/^install jffs2.*/install jffs2 /bin/true/g' /etc/modprobe.d/jffs2.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/jffs2.conf
	echo "install jffs2 /bin/true" >> /etc/modprobe.d/jffs2.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'jffs2' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - jffs2
  tags:
    - kernel_module_jffs2_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80139-9
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of hfs   [ref]rule

To configure the system to prevent the hfs kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install hfs /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80140-7

References:  CM-7, 1.1.1.4, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install hfs" /etc/modprobe.d/hfs.conf ; then
	sed -i 's/^install hfs.*/install hfs /bin/true/g' /etc/modprobe.d/hfs.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/hfs.conf
	echo "install hfs /bin/true" >> /etc/modprobe.d/hfs.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'hfs' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - hfs
  tags:
    - kernel_module_hfs_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80140-7
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of hfsplus   [ref]rule

To configure the system to prevent the hfsplus kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install hfsplus /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80141-5

References:  CM-7, 1.1.1.5, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install hfsplus" /etc/modprobe.d/hfsplus.conf ; then
	sed -i 's/^install hfsplus.*/install hfsplus /bin/true/g' /etc/modprobe.d/hfsplus.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/hfsplus.conf
	echo "install hfsplus /bin/true" >> /etc/modprobe.d/hfsplus.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'hfsplus' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - hfsplus
  tags:
    - kernel_module_hfsplus_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80141-5
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of squashfs   [ref]rule

To configure the system to prevent the squashfs kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install squashfs /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80142-3

References:  CM-7, 1.1.1.6, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install squashfs" /etc/modprobe.d/squashfs.conf ; then
	sed -i 's/^install squashfs.*/install squashfs /bin/true/g' /etc/modprobe.d/squashfs.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/squashfs.conf
	echo "install squashfs /bin/true" >> /etc/modprobe.d/squashfs.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'squashfs' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - squashfs
  tags:
    - kernel_module_squashfs_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80142-3
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Disable Mounting of udf   [ref]rule

To configure the system to prevent the udf kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install udf /bin/true
This effectively prevents usage of this uncommon filesystem.

Rationale:

Linux kernel modules which implement filesystems that are not needed by the local system should be disabled.

Severity:  low

Identifiers:  CCE-80143-1

References:  CM-7, 1.1.1.7, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install udf" /etc/modprobe.d/udf.conf ; then
	sed -i 's/^install udf.*/install udf /bin/true/g' /etc/modprobe.d/udf.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/udf.conf
	echo "install udf /bin/true" >> /etc/modprobe.d/udf.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'udf' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - udf
  tags:
    - kernel_module_udf_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-80143-1
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6

Verify Permissions on Important Files and Directories   [ref]group

Permissions 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 1 rule

Verify that All World-Writable Directories Have Sticky Bits Set   [ref]rule

When 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.

Severity:  low

Identifiers:  CCE-80130-8

References:  AC-6, 1.1.21

Restrict Programs from Dangerous Execution Patterns   [ref]group

The recommendations in this section are designed to ensure that the system's features to protect against potentially dangerous program execution are activated. These protections are applied at the system initialization or kernel level, and defend against certain types of badly-configured or compromised programs.

contains 4 rules

Disable Core Dumps   [ref]group

A core dump file is the memory image of an executable program when it was terminated by the operating system due to errant behavior. In most cases, only software developers legitimately need to access these files. The core dump files may also contain sensitive information, or unnecessarily occupy large amounts of disk space.

Once a hard limit is set in /etc/security/limits.conf, a user cannot increase that limit within his or her own session. If access to core dumps is required, consider restricting them to only certain users or groups. See the limits.conf man page for more information.

The core dumps of setuid programs are further protected. The sysctl variable fs.suid_dumpable controls whether the kernel allows core dumps from these programs at all. The default value of 0 is recommended.

contains 2 rules

Disable Core Dumps for All Users   [ref]rule

To disable core dumps for all users, add the following line to /etc/security/limits.conf:

*     hard   core    0

Rationale:

A core dump includes a memory image taken at the time the operating system terminates an application. The memory image could contain sensitive data and is generally useful only for developers trying to debug problems.

Severity:  low

Identifiers:  CCE-80169-6

References:  SC-5, 1.5.1

Remediation Shell script:   (show)

echo "*     hard   core    0" >> /etc/security/limits.conf

Disable Core Dumps for SUID programs   [ref]rule

To set the runtime status of the fs.suid_dumpable kernel parameter, run the following command:

$ sudo sysctl -w fs.suid_dumpable=0
If this is not the system's default value, add the following line to /etc/sysctl.conf:
fs.suid_dumpable = 0

Rationale:

The core dump of a setuid program is more likely to contain sensitive data, as the program itself runs with greater privileges than the user who initiated execution of the program. Disabling the ability for any setuid program to write a core file decreases the risk of unauthorized access of such data.

Severity:  low

Identifiers:  CCE-26900-1

References:  SI-11, 1.5.1

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable


#
# Set runtime for fs.suid_dumpable
#
/sbin/sysctl -q -n -w fs.suid_dumpable=0

#
# If fs.suid_dumpable present in /etc/sysctl.conf, change value to "0"
#	else, add "fs.suid_dumpable = 0" to /etc/sysctl.conf
#
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/sysctl.conf' '^fs.suid_dumpable' "0" 'CCE-26900-1'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Ensure sysctl fs.suid_dumpable is set to 0
  sysctl:
    name: fs.suid_dumpable
    value: 0
    state: present
    reload: yes
  tags:
    - sysctl_fs_suid_dumpable
    - low_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-26900-1
    - NIST-800-53-SI-11

Enable ExecShield   [ref]group

ExecShield describes kernel features that provide protection against exploitation of memory corruption errors such as buffer overflows. These features include random placement of the stack and other memory regions, prevention of execution in memory that should only hold data, and special handling of text buffers. These protections are enabled by default on 32-bit systems and controlled through sysctl variables kernel.exec-shield and kernel.randomize_va_space. On the latest 64-bit systems, kernel.exec-shield cannot be enabled or disabled with sysctl.

contains 2 rules

Enable ExecShield   [ref]rule

By default on Red Hat Enterprise Linux 7 64-bit systems, ExecShield is enabled and can only be disabled if the hardware does not support ExecShield or is disabled in /etc/default/grub. For Red Hat Enterprise Linux 7 32-bit systems, sysctl can be used to enable ExecShield.

Rationale:

ExecShield uses the segmentation feature on all x86 systems to prevent execution in memory higher than a certain address. It writes an address as a limit in the code segment descriptor, to control where code can be executed, on a per-process basis. When the kernel places a process's memory regions such as the stack and heap higher than this address, the hardware prevents execution in that address range. This is enabled by default on the latest Red Hat and Fedora systems if supported by the hardware.

Severity:  medium

Identifiers:  CCE-27211-2

References:  SC-39, 2530, 3.1.7, 1.5.2

Remediation Shell script:   (show)



if [ $(getconf LONG_BIT) = "32" ] ; then
  #
  # Set runtime for kernel.exec-shield
  #
  sysctl -q -n -w kernel.exec-shield=1

  #
  # If kernel.exec-shield present in /etc/sysctl.conf, change value to "1"
  #	else, add "kernel.exec-shield = 1" to /etc/sysctl.conf
  #
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

  replace_or_append '/etc/sysctl.conf' '^kernel.exec-shield' '1' 'CCE-27211-2'
fi

if [ $(getconf LONG_BIT) = "64" ] ; then
  if grep --silent noexec /boot/grub2/grub*.cfg ; then 
        sed -i "s/noexec.*//g" /etc/default/grub
        sed -i "s/noexec.*//g" /etc/grub.d/*
        GRUBCFG=`ls | grep '.cfg$'`
        grub2-mkconfig -o /boot/grub2/$GRUBCFG
  fi
fi

Enable Randomized Layout of Virtual Address Space   [ref]rule

To set the runtime status of the kernel.randomize_va_space kernel parameter, run the following command:

$ sudo sysctl -w kernel.randomize_va_space=2
If this is not the system's default value, add the following line to /etc/sysctl.conf:
kernel.randomize_va_space = 2

Rationale:

Address space layout randomization (ASLR) makes it more difficult for an attacker to predict the location of attack code they have introduced into a process's address space during an attempt at exploitation. Additionally, ASLR makes it more difficult for an attacker to know the location of existing code in order to re-purpose it using return oriented programming (ROP) techniques.

Severity:  medium

Identifiers:  CCE-27127-0

References:  SC-30(2), 1.5.1, 3.1.7

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' 'CCE-27127-0'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Ensure sysctl kernel.randomize_va_space is set to 2
  sysctl:
    name: kernel.randomize_va_space
    value: 2
    state: present
    reload: yes
  tags:
    - sysctl_kernel_randomize_va_space
    - medium_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-27127-0
    - NIST-800-53-SC-30(2)
    - NIST-800-171-3.1.7

SELinux   [ref]group

SELinux is a feature of the Linux kernel which can be used to guard against misconfigured or compromised programs. SELinux enforces the idea that programs should be limited in what files they can access and what actions they can take.

The default SELinux policy, as configured on Red Hat Enterprise Linux 7, has been sufficiently developed and debugged that it should be usable on almost any Red Hat system with minimal configuration and a small amount of system administrator training. This policy prevents system services - including most of the common network-visible services such as mail servers, FTP servers, and DNS servers - from accessing files which those services have no valid reason to access. This action alone prevents a huge amount of possible damage from network attacks against services, from trojaned software, and so forth.

This guide recommends that SELinux be enabled using the default (targeted) policy on every Red Hat system, unless that system has unusual requirements which make a stronger policy appropriate.

For more information on SELinux, see https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide

contains 6 rules

Ensure SELinux Not Disabled in /etc/default/grub   [ref]rule

SELinux can be disabled at boot time by an argument in /etc/default/grub. Remove any instances of selinux=0 from the kernel arguments in that file to prevent SELinux from being disabled at boot.

Rationale:

Disabling a major host protection feature, such as SELinux, at boot time prevents it from confining system services at boot time. Further, it increases the chances that it will remain off during system operation.

Severity:  medium

Identifiers:  CCE-26961-3

References:  AC-3, AC-3(3), AC-3(4), AC-4, AC-6, AU-9, SI-6(a), 22, 32, 1.6.1.1, 3.1.2, 3.7.2

Remediation Shell script:   (show)

sed -i --follow-symlinks "s/selinux=0//gI" /etc/default/grub /etc/grub2.cfg /etc/grub.d/*
sed -i --follow-symlinks "s/enforcing=0//gI" /etc/default/grub /etc/grub2.cfg /etc/grub.d/*
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Ensure SELinux Not Disabled in /etc/default/grub
  replace:
    dest: /etc/default/grub
    regexp: selinux=0
  tags:
    - enable_selinux_bootloader
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-26961-3
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)
    - NIST-800-53-AC-3(4)
    - NIST-800-53-AC-4
    - NIST-800-53-AC-6
    - NIST-800-53-AU-9
    - NIST-800-53-SI-6(a)
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2

Ensure SELinux State is Enforcing   [ref]rule

The SELinux state should be set to enforcing at system boot time. In the file /etc/selinux/config, add or correct the following line to configure the system to boot into enforcing mode:

SELINUX=enforcing

Rationale:

Setting the SELinux state to enforcing ensures SELinux is able to confine potentially compromised processes to the security policy, which is designed to prevent them from causing damage to the system or further elevating their privileges.

Severity:  high

Remediation Shell script:   (show)


var_selinux_state="enforcing"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state 'CCE-27334-2' '%s=%s'

fixfiles onboot
fixfiles -f relabel
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Ensure SELinux State is Enforcing (persistent)"
  selinux:
    state: enforcing
  tags:
    - selinux_state
    - high_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27334-2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)
    - NIST-800-53-AC-3(4)
    - NIST-800-53-AC-4
    - NIST-800-53-AC-6
    - NIST-800-53-AU-9
    - NIST-800-53-SI-6(a)
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2

Configure SELinux Policy   [ref]rule

The SELinux targeted policy is appropriate for general-purpose desktops and servers, as well as systems in many other roles. To configure the system to use this policy, add or correct the following line in /etc/selinux/config:

SELINUXTYPE=targeted
Other policies, such as mls, provide additional security labeling and greater confinement but are not compatible with many general-purpose use cases.

Rationale:

Setting the SELinux policy to targeted or a more specialized policy ensures the system will confine processes that are likely to be targeted for exploitation, such as network or system services.

Note: During the development or debugging of SELinux modules, it is common to temporarily place non-production systems in permissive mode. In such temporary cases, SELinux policies should be developed, and once work is completed, the system should be reconfigured to targeted.

Severity:  high

Identifiers:  CCE-27279-9

References:  RHEL-07-020220, AC-3, AC-3(3), AC-3(4), AC-4, AC-6, AU-9, SI-6(a), 2696, 1.6.1.3, SRG-OS-000445-GPOS-00199, 3.1.2, 3.7.2

Remediation Shell script:   (show)


var_selinux_policy_name="targeted"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/sysconfig/selinux' '^SELINUXTYPE=' $var_selinux_policy_name 'CCE-27279-9' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Configure SELinux Policy"
  selinux:
    policy: targeted
  tags:
    - selinux_policytype
    - high_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27279-9
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)
    - NIST-800-53-AC-3(4)
    - NIST-800-53-AC-4
    - NIST-800-53-AC-6
    - NIST-800-53-AU-9
    - NIST-800-53-SI-6(a)
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2

Uninstall setroubleshoot Package   [ref]rule

The SETroubleshoot service notifies desktop users of SELinux denials. The service provides information around configuration errors, unauthorized intrusions, and other potential errors. The setroubleshoot package can be removed with the following command:

$ sudo yum erase setroubleshoot

Rationale:

The SETroubleshoot service is an unnecessary daemon to have running on a server

Severity:  low

Identifiers:  CCE-80444-3

References:  1.6.1.4

Uninstall mcstrans Package   [ref]rule

The mcstransd daemon provides category label information to client processes requesting information. The label translations are defined in /etc/selinux/targeted/setrans.conf. The mcstrans package can be removed with the following command:

$ sudo yum erase mcstrans

Rationale:

Since this service is not used very often, disable it to reduce the amount of potentially vulnerable code running on the system. NOTE: This rule was added in support of the CIS RHEL6 v1.2.0 benchmark. Please note that Red Hat does not feel this rule is security relevant.

Severity:  low

Identifiers:  CCE-80445-0

References:  1.6.1.5

Ensure No Daemons are Unconfined by SELinux   [ref]rule

Daemons for which the SELinux policy does not contain rules will inherit the context of the parent process. Because daemons are launched during startup and descend from the init process, they inherit the initrc_t context.

To check for unconfined daemons, run the following command:

$ sudo ps -eZ | egrep "initrc" | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }'
It should produce no output in a well-configured system.

Rationale:

Daemons which run with the initrc_t context may cause AVC denials, or allow privileges that the daemon does not require.

Severity:  medium

Identifiers:  CCE-27288-0

References:  AC-6, AU-9, CM-7, 1.6.1.6, 3.1.2, 3.1.5, 3.7.2

Account and Access Control   [ref]group

In 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 Red Hat Enterprise Linux 7.

contains 10 rules

Protect Accounts by Restricting Password-Based Login   [ref]group

Conventionally, 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

Restrict Root Logins   [ref]group

Direct root logins should be allowed only for emergency use. In normal situations, the administrator should access the system via a unique unprivileged account, and then use su or sudo to execute privileged commands. Discouraging administrators from accessing the root account directly ensures an audit trail in organizations with multiple administrators. Locking down the channels through which root can connect directly also reduces opportunities for password-guessing against the root account. The login program uses the file /etc/securetty to determine which interfaces should allow root logins. The virtual devices /dev/console and /dev/tty* represent the system consoles (accessible via the Ctrl-Alt-F1 through Ctrl-Alt-F6 keyboard sequences on a default installation). The default securetty file also contains /dev/vc/*. These are likely to be deprecated in most environments, but may be retained for compatibility. Root should also be prohibited from connecting via network protocols. Other sections of this document include guidance describing how to prevent root from logging in via SSH.

contains 1 rule

Direct root Logins Not Allowed   [ref]rule

To further limit access to the root account, administrators can disable root logins at the console by editing the /etc/securetty file. This file lists all devices the root user is allowed to login to. If the file does not exist at all, the root user can login through any communication device on the system, whether via the console or via a raw network interface. This is dangerous as user can login to the system as root via Telnet, which sends the password in plain text over the network. By default, Red Hat Enteprise Linux's /etc/securetty file only allows the root user to login at the console physically attached to the system. To prevent root from logging in, remove the contents of this file. To prevent direct root logins, remove the contents of this file by typing the following command:

$ sudo echo > /etc/securetty

Rationale:

Disabling direct root logins ensures proper accountability and multifactor authentication to privileged accounts. Users will first login, then escalate to privileged (root) access via su / sudo. This is required for FISMA Low and FISMA Moderate systems.

Severity:  medium

Identifiers:  CCE-27294-8

References:  IA-2(1), 5.5, 3.1.1, 3.1.6

Remediation Shell script:   (show)

echo > /etc/securetty
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Direct root Logins Not Allowed"
  shell: echo > /etc/securetty
  tags:
    - no_direct_root_logins
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27294-8
    - NIST-800-53-IA-2(1)
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.6

Set Password Expiration Parameters   [ref]group

The file /etc/login.defs controls several password-related settings. Programs such as passwd, su, and login consult /etc/login.defs to determine behavior with regard to password aging, expiration warnings, and length. See the man page login.defs(5) for more information.

Users should be forced to change their passwords, in order to decrease the utility of compromised passwords. However, the need to change passwords often should be balanced against the risk that users will reuse or write down passwords if forced to change them too often. Forcing password changes every 90-360 days, depending on the environment, is recommended. Set the appropriate value as PASS_MAX_DAYS and apply it to existing accounts with the -M flag.

The PASS_MIN_DAYS (-m) setting prevents password changes for 7 days after the first change, to discourage password cycling. If you use this setting, train users to contact an administrator for an emergency password change in case a new password becomes compromised. The PASS_WARN_AGE (-W) setting gives users 7 days of warnings at login time that their passwords are about to expire.

For example, for each existing human user USER, expiration parameters could be adjusted to a 180 day maximum password age, 7 day minimum password age, and 7 day warning period with the following command:

$ sudo chage -M 180 -m 7 -W 7 USER

contains 1 rule

Protect Accounts by Configuring PAM   [ref]group

PAM, or Pluggable Authentication Modules, is a system which implements modular authentication for Linux programs. PAM provides a flexible and configurable architecture for authentication, and it should be configured to minimize exposure to unnecessary risk. This section contains guidance on how to accomplish that.

PAM is implemented as a set of shared objects which are loaded and invoked whenever an application wishes to authenticate a user. Typically, the application must be running as root in order to take advantage of PAM, because PAM's modules often need to be able to access sensitive stores of account information, such as /etc/shadow. Traditional privileged network listeners (e.g. sshd) or SUID programs (e.g. sudo) already meet this requirement. An SUID root application, userhelper, is provided so that programs which are not SUID or privileged themselves can still take advantage of PAM.

PAM looks in the directory /etc/pam.d for application-specific configuration information. For instance, if the program login attempts to authenticate a user, then PAM's libraries follow the instructions in the file /etc/pam.d/login to determine what actions should be taken.

One very important file in /etc/pam.d is /etc/pam.d/system-auth. This file, which is included by many other PAM configuration files, defines 'default' system authentication measures. Modifying this file is a good way to make far-reaching authentication changes, for instance when implementing a centralized authentication service.

Warning:  Be careful when making changes to PAM's configuration files. The syntax for these files is complex, and modifications can have unexpected consequences. The default configurations shipped with applications should be sufficient for most users.
Warning:  Running authconfig or system-config-authentication will re-write the PAM configuration files, destroying any manually made changes and replacing them with a series of system defaults. One reference to the configuration file syntax can be found at http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/sag-configuration-file.html .
contains 1 rule

Set Lockouts for Failed Password Attempts   [ref]group

The pam_faillock PAM module provides the capability to lock out user accounts after a number of failed login attempts. Its documentation is available in /usr/share/doc/pam-VERSION/txts/README.pam_faillock.

Warning:  Locking out user accounts presents the risk of a denial-of-service attack. The lockout policy must weigh whether the risk of such a denial-of-service attack outweighs the benefits of thwarting password guessing attacks.
contains 1 rule

Limit Password Reuse   [ref]rule

Do not allow users to reuse recent passwords. This can be accomplished by using the remember option for the pam_unix or pam_pwhistory PAM modules.

In the file /etc/pam.d/system-auth, append remember=5 to the line which refers to the pam_unix.so or pam_pwhistory.somodule, as shown below:

  • for the pam_unix.so case:
    password sufficient pam_unix.so ...existing_options... remember=5
  • for the pam_pwhistory.so case:
    password requisite pam_pwhistory.so ...existing_options... remember=5
The DoD STIG requirement is 5 passwords.

Rationale:

Preventing re-use of previous passwords helps ensure that a compromised password is not re-used by a user.

Severity:  medium

Remediation Shell script:   (show)


var_password_pam_unix_remember="5"

if grep -q "remember=" /etc/pam.d/system-auth; then   
	sed -i --follow-symlinks "s/\(^password.*sufficient.*pam_unix.so.*\)\(\(remember *= *\)[^ $]*\)/\1remember=$var_password_pam_unix_remember/" /etc/pam.d/system-auth
else
	sed -i --follow-symlinks "/^password[[:space:]]\+sufficient[[:space:]]\+pam_unix.so/ s/$/ remember=$var_password_pam_unix_remember/" /etc/pam.d/system-auth
fi

Protect Physical Console Access   [ref]group

It is impossible to fully protect a system from an attacker with physical access, so securing the space in which the system is located should be considered a necessary step. However, there are some steps which, if taken, make it more difficult for an attacker to quickly or undetectably modify a system from its console.

contains 6 rules

Set Boot Loader Password   [ref]group

During the boot process, the boot loader is responsible for starting the execution of the kernel and passing options to it. The boot loader allows for the selection of different kernels - possibly on different partitions or media. The default Red Hat Enterprise Linux boot loader for x86 systems is called GRUB2. Options it can pass to the kernel include single-user mode, which provides root access without any authentication, and the ability to disable SELinux. To prevent local users from modifying the boot parameters and endangering security, protect the boot loader configuration with a password and ensure its configuration file's permissions are set properly.

contains 5 rules

Verify /boot/grub2/grub.cfg User Ownership   [ref]rule

The file /boot/grub2/grub.cfg should be owned by the root user to prevent destruction or modification of the file. To properly set the owner of /boot/grub2/grub.cfg, run the command:

$ sudo chown root /boot/grub2/grub.cfg

Rationale:

Only root should be able to modify important boot parameters.

Severity:  medium

Identifiers:  CCE-26860-7

References:  AC-6(7), 225, Req-7.1, 1.4.1, 5.5.2.2, 3.4.5

Remediation Shell script:   (show)

chown root /boot/grub2/grub.cfg

Verify /boot/grub2/grub.cfg Group Ownership   [ref]rule

The file /boot/grub2/grub.cfg should be group-owned by the root group to prevent destruction or modification of the file. To properly set the group owner of /boot/grub2/grub.cfg, run the command:

$ sudo chgrp root /boot/grub2/grub.cfg

Rationale:

The root group is a highly-privileged group. Furthermore, the group-owner of this file should not have any access privileges anyway.

Severity:  medium

Identifiers:  CCE-26812-8

References:  AC-6(7), 225, Req-7.1, 1.4.1, 5.5.2.2, 3.4.5

Remediation Shell script:   (show)

chgrp root /boot/grub2/grub.cfg

Verify /boot/grub2/grub.cfg Permissions   [ref]rule

File permissions for /boot/grub2/grub.cfg should be set to 600. To properly set the permissions of /boot/grub2/grub.cfg, run the command:

$ sudo chmod 600 /boot/grub2/grub.cfg

Rationale:

Proper permissions ensure that only the root user can modify important boot parameters.

Severity:  medium

Identifiers:  CCE-27054-6

References:  AC-6(7), 225, 1.4.1, 3.4.5

Remediation Shell script:   (show)

chmod 600 /boot/grub2/grub.cfg

Set Boot Loader Password   [ref]rule

The grub2 boot loader should have a superuser account and password protection enabled to protect boot-time settings.

To do so, select a superuser account and password and add them into the /etc/grub.d/01_users configuration file.

Since plaintext passwords are a security risk, generate a hash for the pasword by running the following command:

$ grub2-mkpasswd-pbkdf2
When prompted, enter the password that was selected and insert the returned password hash into the /etc/grub.d/01_users configuration file immediately after the superuser account. (Use the output from grub2-mkpasswd-pbkdf2 as the value of password-hash):
password_pbkdf2 superusers-account password-hash
NOTE: It is recommended not to use common administrator account names like root, admin, or administrator for the grub2 superuser account.

To meet FISMA Moderate, the bootloader superuser account and password MUST differ from the root account and password. Once the superuser account and password have been added, update the grub.cfg file by running:
grub2-mkconfig -o /boot/grub2/grub.cfg
NOTE: Do NOT manually add the superuser account and password to the grub.cfg file as the grub2-mkconfig command overwrites this file.

Warning:  To prevent hard-coded passwords, automatic remediation of this control is not available. Remediation must be automated as a component of machine provisioning, or followed manually as outlined above.
Rationale:

Password protection on the boot loader configuration ensures users with physical access cannot trivially alter important bootloader settings. These include which kernel to use, and whether to enter single-user mode. For more information on how to configure the grub2 superuser account and password, please refer to

Severity:  high

Identifiers:  CCE-27309-4

References:  RHEL-07-010480, IA-2(1), IA-5(e), AC-3, 213, SRG-OS-000080-GPOS-00048, 1.4.2, 3.4.5

Set the UEFI Boot Loader Password   [ref]rule

The UEFI grub2 boot loader should have a superuser account and password protection enabled to protect boot-time settings.

To do so, select a superuser account and password and add them into the /etc/grub.d/01_users configuration file.

Since plaintext passwords are a security risk, generate a hash for the pasword by running the following command:

$ grub2-mkpasswd-pbkdf2
When prompted, enter the password that was selected and insert the returned password hash into the /etc/grub.d/01_users configuration file immediately after the superuser account. (Use the output from grub2-mkpasswd-pbkdf2 as the value of password-hash):
password_pbkdf2 superusers-account password-hash
NOTE: It is recommended not to use common administrator account names like root, admin, or administrator for the grub2 superuser account.

To meet FISMA Moderate, the bootloader superuser account and password MUST differ from the root account and password. Once the superuser account and password have been added, update the grub.cfg file by running:
grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
NOTE: Do NOT manually add the superuser account and password to the grub.cfg file as the grub2-mkconfig command overwrites this file.

Warning:  To prevent hard-coded passwords, automatic remediation of this control is not available. Remediation must be automated as a component of machine provisioning, or followed manually as outlined above.
Rationale:

Password protection on the boot loader configuration ensures users with physical access cannot trivially alter important bootloader settings. These include which kernel to use, and whether to enter single-user mode. For more information on how to configure the grub2 superuser account and password, please refer to

Severity:  medium

Identifiers:  CCE-80354-4

References:  RHEL-07-010490, AC-3, 213, SRG-OS-000080-GPOS-00048, 3.4.5, 1.4.2

Require Authentication for Single User Mode   [ref]rule

Single-user mode is intended as a system recovery method, providing a single user root access to the system by providing a boot option at startup. By default, no authentication is performed if single-user mode is selected.

By default, single-user mode is protected by requiring a password and is set in /usr/lib/systemd/system/rescue.service.

Rationale:

This prevents attackers with physical access from trivially bypassing security on the machine and gaining root access. Such accesses are further prevented by configuring the bootloader password.

Severity:  medium

Identifiers:  CCE-27287-2

References:  IA-2(1), AC-3, 213, 3.1.1, 3.4.5, 1.4.3

Remediation Shell script:   (show)

grep -q "^ExecStart=\-.*/sbin/sulogin" /usr/lib/systemd/system/rescue.service
if ! [ $? -eq 0 ]; then
    sed -i "s/ExecStart=-.*-c \"/&\/sbin\/sulogin; /g" /usr/lib/systemd/system/rescue.service
fi

Warning Banners for System Accesses   [ref]group

Each system should expose as little information about itself as possible.

System banners, which are typically displayed just before a login prompt, give out information about the service or the host's operating system. This might include the distribution name and the system kernel version, and the particular version of a network service. This information can assist intruders in gaining access to the system as it can reveal whether the system is running vulnerable software. Most network services can be configured to limit what information is displayed.

Many organizations implement security policies that require a system banner provide notice of the system's ownership, provide warning to unauthorized users, and remind authorized users of their consent to monitoring.

contains 1 rule

Modify the System Login Banner   [ref]rule

To configure the system login banner edit /etc/issue. Replace the default text with a message compliant with the local site policy or a legal disclaimer. The DoD required text is either:

You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions:
-The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations.
-At any time, the USG may inspect and seize data stored on this IS.
-Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose.
-This IS includes security measures (e.g., authentication and access controls) to protect USG interests -- not for your personal benefit or privacy.
-Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details.


OR:

I've read & consent to terms in IS user agreem't.

Rationale:

Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

System use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.

Severity:  medium

Remediation Shell script:   (show)


login_banner_text="--[\s\n]+WARNING[\s\n]+--[\s\n]*This[\s\n]+system[\s\n]+is[\s\n]+for[\s\n]+the[\s\n]+use[\s\n]+of[\s\n]+authorized[\s\n]+users[\s\n]+only.[\s\n]+Individuals[\s\n]*using[\s\n]+this[\s\n]+computer[\s\n]+system[\s\n]+without[\s\n]+authority[\s\n]+or[\s\n]+in[\s\n]+excess[\s\n]+of[\s\n]+their[\s\n]*authority[\s\n]+are[\s\n]+subject[\s\n]+to[\s\n]+having[\s\n]+all[\s\n]+their[\s\n]+activities[\s\n]+on[\s\n]+this[\s\n]+system[\s\n]*monitored[\s\n]+and[\s\n]+recorded[\s\n]+by[\s\n]+system[\s\n]+personnel.[\s\n]+Anyone[\s\n]+using[\s\n]+this[\s\n]*system[\s\n]+expressly[\s\n]+consents[\s\n]+to[\s\n]+such[\s\n]+monitoring[\s\n]+and[\s\n]+is[\s\n]+advised[\s\n]+that[\s\n]*if[\s\n]+such[\s\n]+monitoring[\s\n]+reveals[\s\n]+possible[\s\n]+evidence[\s\n]+of[\s\n]+criminal[\s\n]+activity[\s\n]*system[\s\n]+personal[\s\n]+may[\s\n]+provide[\s\n]+the[\s\n]+evidence[\s\n]+of[\s\n]+such[\s\n]+monitoring[\s\n]+to[\s\n]+law[\s\n]*enforcement[\s\n]+officials."

# There was a regular-expression matching various banners, needs to be expanded
expanded=$(echo "$login_banner_text" | sed 's/\[\\s\\n\][+*]/ /g;s/\\//g;s/[^-]- /\n\n-/g')
formatted=$(echo "$expanded" | fold -sw 80)

cat <<EOF >/etc/issue
$formatted
EOF

printf "\n" >> /etc/issue

Network Configuration and Firewalls   [ref]group

Most systems must be connected to a network of some sort, and this brings with it the substantial risk of network attack. This section discusses the security impact of decisions about networking which must be made when configuring a system.

This section also discusses firewalls, network access controls, and other network security frameworks, which allow system-level rules to be written that can limit an attackers' ability to connect to your system. These rules can specify that network traffic should be allowed or denied from certain IP addresses, hosts, and networks. The rules can also specify which of the system's network services are available to particular hosts or networks.

contains 2 rules

Uncommon Network Protocols   [ref]group

The system includes support for several network protocols which are not commonly used. Although security vulnerabilities in kernel networking code are not frequently discovered, the consequences can be dramatic. Ensuring uncommon network protocols are disabled reduces the system's risk to attacks targeted at its implementation of those protocols.

Warning:  Although these protocols are not commonly used, avoid disruption in your network environment by ensuring they are not needed prior to disabling them.
contains 2 rules

Disable DCCP Support   [ref]rule

The Datagram Congestion Control Protocol (DCCP) is a relatively new transport layer protocol, designed to support streaming media and telephony. To configure the system to prevent the dccp kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install dccp /bin/true

Rationale:

Disabling DCCP protects the system against exploitation of any flaws in its implementation.

Severity:  medium

Identifiers:  CCE-26828-4

References:  CM-7, http://iase.disa.mil/stigs/cci/Pages/index.aspx, 3.5.1, 5.10.1, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install dccp" /etc/modprobe.d/dccp.conf ; then
	sed -i 's/^install dccp.*/install dccp /bin/true/g' /etc/modprobe.d/dccp.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/dccp.conf
	echo "install dccp /bin/true" >> /etc/modprobe.d/dccp.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'dccp' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - dccp
  tags:
    - kernel_module_dccp_disabled
    - medium_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-26828-4
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6
    - CJIS-5.10.1

Disable SCTP Support   [ref]rule

The Stream Control Transmission Protocol (SCTP) is a transport layer protocol, designed to support the idea of message-oriented communication, with several streams of messages within one connection. To configure the system to prevent the sctp kernel module from being loaded, add the following line to a file in the directory /etc/modprobe.d:

install sctp /bin/true

Rationale:

Disabling SCTP protects the system against exploitation of any flaws in its implementation.

Severity:  medium

Identifiers:  CCE-27106-4

References:  CM-7, http://iase.disa.mil/stigs/cci/Pages/index.aspx, 3.5.2, 5.10.1, 3.4.6

Remediation Shell script:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
if grep --silent "^install sctp" /etc/modprobe.d/sctp.conf ; then
	sed -i 's/^install sctp.*/install sctp /bin/true/g' /etc/modprobe.d/sctp.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/sctp.conf
	echo "install sctp /bin/true" >> /etc/modprobe.d/sctp.conf
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: "Ensure kernel module 'sctp' is disabled"
  lineinfile:
    create=yes
    dest="/etc/modprobe.d/{{item}}.conf"
    regexp="{{item}}"
    line="install {{item}} /bin/true"
  with_items:
    - sctp
  tags:
    - kernel_module_sctp_disabled
    - medium_severity
    - disable_strategy
    - low_complexity
    - medium_disruption
    - CCE-27106-4
    - NIST-800-53-CM-7
    - NIST-800-171-3.4.6
    - CJIS-5.10.1

Configure Syslog   [ref]group

The syslog service has been the default Unix logging mechanism for many years. It has a number of downsides, including inconsistent log format, lack of authentication for received messages, and lack of authentication, encryption, or reliable transport for messages sent over a network. However, due to its long history, syslog is a de facto standard which is supported by almost all Unix applications.

In Red Hat Enterprise Linux 7, rsyslog has replaced ksyslogd as the syslog daemon of choice, and it includes some additional security features such as reliable, connection-oriented (i.e. TCP) transmission of logs, the option to log to database formats, and the encryption of log data en route to a central logging server. This section discusses how to configure rsyslog for best effect, and how to use tools provided with the system to maintain and monitor logs.

contains 6 rules

Ensure Proper Configuration of Log Files   [ref]group

The file /etc/rsyslog.conf controls where log message are written. These are controlled by lines called rules, which consist of a selector and an action. These rules are often customized depending on the role of the system, the requirements of the environment, and whatever may enable the administrator to most effectively make use of log data. The default rules in Red Hat Enterprise Linux 7 are:

*.info;mail.none;authpriv.none;cron.none                /var/log/messages
authpriv.*                                              /var/log/secure
mail.*                                                  -/var/log/maillog
cron.*                                                  /var/log/cron
*.emerg                                                 *
uucp,news.crit                                          /var/log/spooler
local7.*                                                /var/log/boot.log
See the man page rsyslog.conf(5) for more information. Note that the rsyslog daemon can be configured to use a timestamp format that some log processing programs may not understand. If this occurs, edit the file /etc/rsyslog.conf and add or edit the following line:
$ ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

contains 1 rule

Ensure System Log Files Have Correct Permissions   [ref]rule

The file permissions for all log files written by rsyslog should be set to 600, or more restrictive. These log files are determined by the second part of each Rule line in /etc/rsyslog.conf and typically all appear in /var/log. For each log file LOGFILE referenced in /etc/rsyslog.conf, run the following command to inspect the file's permissions:

$ ls -l LOGFILE
If the permissions are not 600 or more restrictive, run the following command to correct this:
$ sudo chmod 0600 LOGFILE

Rationale:

Log files can contain valuable information regarding system configuration. If the system log files are not protected unauthorized users could change the logged data, eliminating their forensic value.

Severity:  medium

Identifiers:  CCE-80191-0

References:  SI-11, 1314, Req-10.5.1, Req-10.5.2, 4.2.1.3

Remediation Shell script:   (show)


# List of log file paths to be inspected for correct permissions
# * Primarily inspect log file paths listed in /etc/rsyslog.conf
RSYSLOG_ETC_CONFIG="/etc/rsyslog.conf"
# * And also the log file paths listed after rsyslog's $IncludeConfig directive
#   (store the result into array for the case there's shell glob used as value of IncludeConfig)
RSYSLOG_INCLUDE_CONFIG=($(grep -e "\$IncludeConfig[[:space:]]\+[^[:space:];]\+" /etc/rsyslog.conf | cut -d ' ' -f 2))
# Declare an array to hold the final list of different log file paths
declare -a LOG_FILE_PATHS

# Browse each file selected above as containing paths of log files
# ('/etc/rsyslog.conf' and '/etc/rsyslog.d/*.conf' in the default configuration)
for LOG_FILE in "${RSYSLOG_ETC_CONFIG}" "${RSYSLOG_INCLUDE_CONFIG[@]}"
do
	# From each of these files extract just particular log file path(s), thus:
	# * Ignore lines starting with space (' '), comment ('#"), or variable syntax ('$') characters,
	# * Ignore empty lines,
	# * From the remaining valid rows select only fields constituting a log file path
	# Text file column is understood to represent a log file path if and only if all of the following are met:
	# * it contains at least one slash '/' character,
	# * it doesn't contain space (' '), colon (':'), and semicolon (';') characters
	# Search log file for path(s) only in case it exists!
	if [[ -f "${LOG_FILE}" ]]
	then
		MATCHED_ITEMS=$(sed -e "/^[[:space:]|#|$]/d ; s/[^\/]*[[:space:]]*\([^:;[:space:]]*\)/\1/g ; /^$/d" "${LOG_FILE}")
		# Since above sed command might return more than one item (delimited by newline), split the particular
		# matches entries into new array specific for this log file
		readarray -t ARRAY_FOR_LOG_FILE <<< "$MATCHED_ITEMS"
		# Concatenate the two arrays - previous content of $LOG_FILE_PATHS array with
		# items from newly created array for this log file
		LOG_FILE_PATHS=("${LOG_FILE_PATHS[@]}" "${ARRAY_FOR_LOG_FILE[@]}")
		# Delete the temporary array
		unset ARRAY_FOR_LOG_FILE
	fi
done

for PATH in "${LOG_FILE_PATHS[@]}"
do
	# Sanity check - if particular $PATH is empty string, skip it from further processing
	if [ -z "$PATH" ]
	then
		continue
	fi

	# In RHEL 7 we have systemd, so it doesn't make sense to patch/change /etc/rc.d/rc.local,
	# as per BZ https://bugzilla.redhat.com/show_bug.cgi?id=1404381

	# Also for each log file check if its permissions differ from 600. If so, correct them
	if [ "$(/usr/bin/stat -c %a "$PATH")" -ne 600 ]
	then
		/bin/chmod 600 "$PATH"
	fi
done

Rsyslog Logs Sent To Remote Host   [ref]group

If system logs are to be useful in detecting malicious activities, it is necessary to send logs to a remote server. An intruder who has compromised the root account on a system may delete the log entries which indicate that the system was attacked before they are seen by an administrator.

However, it is recommended that logs be stored on the local host in addition to being sent to the loghost, especially if rsyslog has been configured to use the UDP protocol to send messages over a network. UDP does not guarantee reliable delivery, and moderately busy sites will lose log messages occasionally, especially in periods of high traffic which may be the result of an attack. In addition, remote rsyslog messages are not authenticated in any way by default, so it is easy for an attacker to introduce spurious messages to the central log server. Also, some problems cause loss of network connectivity, which will prevent the sending of messages to the central server. For all of these reasons, it is better to store log messages both centrally and on each host, so that they can be correlated if necessary.

contains 1 rule

Ensure Logs Sent To Remote Host   [ref]rule

To configure rsyslog to send logs to a remote log server, open /etc/rsyslog.conf and read and understand the last section of the file, which describes the multiple directives necessary to activate remote logging. Along with these other directives, the system can be configured to forward its logs to a particular log server by adding or correcting one of the following lines, substituting loghost.example.com appropriately. The choice of protocol depends on the environment of the system; although TCP and RELP provide more reliable message delivery, they may not be supported in all environments.
To use UDP for log message delivery:

*.* @loghost.example.com

To use TCP for log message delivery:
*.* @@loghost.example.com

To use RELP for log message delivery:
*.* :omrelp:loghost.example.com

There must be a resolvable DNS CNAME or Alias record set to "(N/A)" for logs to be sent correctly to the centralized logging utility.

Rationale:

A log server (loghost) receives syslog messages from one or more systems. This data can be used as an additional log source in the event a system is compromised and its local logs are suspect. Forwarding log messages to a remote loghost also provides system administrators with a centralized place to view the status of multiple hosts within the enterprise.

Severity:  low

Identifiers:  CCE-27343-3

References:  RHEL-07-031000, AU-3(2), AU-4(1), AU-9, 366, 1348, 136, 1851, 4.2.1.4, SRG-OS-000480-GPOS-00227

Remediation Shell script:   (show)


rsyslog_remote_loghost_address="(N/A)"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/rsyslog.conf' '^\*\.\*' "@@$rsyslog_remote_loghost_address" 'CCE-27343-3' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Set rsyslog remote loghost to (N/A)"
  lineinfile:
    dest: /etc/rsyslog.conf
    regexp: "^\\*\\.\\*"
    line: "*.* @@(N/A)"
  tags:
    - rsyslog_remote_loghost
    - low_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27343-3
    - NIST-800-53-AU-3(2)
    - NIST-800-53-AU-4(1)
    - NIST-800-53-AU-9

Configure rsyslogd to Accept Remote Messages If Acting as a Log Server   [ref]group

By default, rsyslog does not listen over the network for log messages. If needed, modules can be enabled to allow the rsyslog daemon to receive messages from other systems and for the system thus to act as a log server. If the system is not a log server, then lines concerning these modules should remain commented out.

contains 2 rules

Enable rsyslog to Accept Messages via TCP, if Acting As Log Server   [ref]rule

The rsyslog daemon should not accept remote messages unless the system acts as a log server. If the system needs to act as a central log server, add the following lines to /etc/rsyslog.conf to enable reception of messages over TCP:

$ModLoad imtcp
$InputTCPServerRun 514

Rationale:

If the system needs to act as a log server, this ensures that it can receive messages over a reliable TCP connection.

Severity:  low

Identifiers:  CCE-80193-6

References:  AU-9, 4.2.1.5

Enable rsyslog to Accept Messages via UDP, if Acting As Log Server   [ref]rule

The rsyslog daemon should not accept remote messages unless the system acts as a log server. If the system needs to act as a central log server, add the following lines to /etc/rsyslog.conf to enable reception of messages over UDP:

$ModLoad imudp
$UDPServerRun 514

Rationale:

Many devices, such as switches, routers, and other Unix-like systems, may only support the traditional syslog transmission over UDP. If the system must act as a log server, this enables it to receive their messages as well.

Severity:  low

Identifiers:  CCE-80194-4

References:  AU-9, 4.2.1.5

Ensure rsyslog is Installed   [ref]rule

Rsyslog is installed by default. The rsyslog package can be installed with the following command:

$ sudo yum install rsyslog

Rationale:

The rsyslog package provides the rsyslog daemon, which provides system logging services.

Severity:  medium

Identifiers:  CCE-80187-8

References:  AU-9(2), 1311, 1312, 4.2.3

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:enable
# Function to install or uninstall packages on RHEL and Fedora systems.
#
# Example Call(s):
#
#     package_command install aide
#     package_command remove telnet-server
#
function package_command {

# Load function arguments into local variables
local package_operation=$1
local package=$2

# Check sanity of the input
if [ $# -ne "2" ]
then
  echo "Usage: package_command 'install/uninstall' 'rpm_package_name"
  echo "Aborting."
  exit 1
fi

# If dnf is installed, use dnf; otherwise, use yum
if [ -f "/usr/bin/dnf" ] ; then
  install_util="/usr/bin/dnf"
else
  install_util="/usr/bin/yum"
fi

if [ "$package_operation" != 'remove' ] ; then
  # If the rpm is not installed, install the rpm
  if ! /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
else
  # If the rpm is installed, uninstall the rpm
  if /bin/rpm -q --quiet $package; then
    $install_util -y $package_operation $package
  fi
fi

}

package_command install rsyslog
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
- name: "Ensure rsyslog is installed"
  package:
    name="{{item}}"
    state=present
  with_items:
    - rsyslog
  tags:
    - package_rsyslog_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - CCE-80187-8
    - NIST-800-53-AU-9(2)

Remediation Puppet snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
include install_rsyslog

class install_rsyslog {
  package { 'rsyslog':
    ensure => 'installed',
  }
}
Remediation Anaconda snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable

package --add=rsyslog

Enable rsyslog Service   [ref]rule

The rsyslog service provides syslog-style logging by default on Red Hat Enterprise Linux 7. The rsyslog service can be enabled with the following command:

$ sudo systemctl enable rsyslog.service

Rationale:

The rsyslog service must be running in order to provide logging services, which are essential to system administration.

Severity:  medium

Identifiers:  CCE-80188-6

References:  AU-4(1), AU-12, 1311, 1312, 1557, 1851, 4.2.1.1

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:enable
# Function to enable/disable and start/stop services on RHEL and Fedora systems.
#
# Example Call(s):
#
#     service_command enable bluetooth
#     service_command disable bluetooth.service
#
#     Using xinetd:
#     service_command disable rsh.socket xinetd=rsh
#
function service_command {

# Load function arguments into local variables
local service_state=$1
local service=$2
local xinetd=$(echo $3 | cut -d'=' -f2)

# Check sanity of the input
if [ $# -lt "2" ]
then
  echo "Usage: service_command 'enable/disable' 'service_name.service'"
  echo
  echo "To enable or disable xinetd services add \'xinetd=service_name\'"
  echo "as the last argument"  
  echo "Aborting."
  exit 1
fi

# If systemctl is installed, use systemctl command; otherwise, use the service/chkconfig commands
if [ -f "/usr/bin/systemctl" ] ; then
  service_util="/usr/bin/systemctl"
else
  service_util="/sbin/service"
  chkconfig_util="/sbin/chkconfig"
fi

# If disable is not specified in arg1, set variables to enable services.
# Otherwise, variables are to be set to disable services.
if [ "$service_state" != 'disable' ] ; then
  service_state="enable"
  service_operation="start"
  chkconfig_state="on"
else
  service_state="disable"
  service_operation="stop"
  chkconfig_state="off"
fi

# If chkconfig_util is not empty, use chkconfig/service commands.
if ! [ "x$chkconfig_util" = x ] ; then
  $service_util $service $service_operation
  $chkconfig_util --level 0123456 $service $chkconfig_state
else
  $service_util $service_operation $service
  $service_util $service_state $service
fi

# Test if local variable xinetd is empty using non-bashism.
# If empty, then xinetd is not being used.
if ! [ "x$xinetd" = x ] ; then
  grep -qi disable /etc/xinetd.d/$xinetd && \

  if ! [ "$service_operation" != 'disable' ] ; then
    sed -i "s/disable.*/disable         = no/gI" /etc/xinetd.d/$xinetd
  else
    sed -i "s/disable.*/disable         = yes/gI" /etc/xinetd.d/$xinetd
  fi
fi

}

service_command enable rsyslog
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
- name: "Enable service rsyslog"
  service:
    name="{{item}}"
    enabled="yes"
    state="started"
  with_items:
    - rsyslog
  tags:
    - service_rsyslog_enabled
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - CCE-80188-6
    - NIST-800-53-AU-4(1)
    - NIST-800-53-AU-12

System Accounting with auditd   [ref]group

The audit service provides substantial capabilities for recording system activities. By default, the service audits about SELinux AVC denials and certain types of security-relevant events such as system logins, account modifications, and authentication events performed by programs such as sudo. Under its default configuration, auditd has modest disk space requirements, and should not noticeably impact system performance.

NOTE: The Linux Audit daemon auditd can be configured to use the augenrules program to read audit rules files (*.rules) located in /etc/audit/rules.d location and compile them to create the resulting form of the /etc/audit/audit.rules configuration file during the daemon startup (default configuration). Alternatively, the auditd daemon can use the auditctl utility to read audit rules from the /etc/audit/audit.rules configuration file during daemon startup, and load them into the kernel. The expected behavior is configured via the appropriate ExecStartPost directive setting in the /usr/lib/systemd/system/auditd.service configuration file. To instruct the auditd daemon to use the augenrules program to read audit rules (default configuration), use the following setting:

ExecStartPost=-/sbin/augenrules --load
in the /usr/lib/systemd/system/auditd.service configuration file. In order to instruct the auditd daemon to use the auditctl utility to read audit rules, use the following setting:
ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules
in the /usr/lib/systemd/system/auditd.service configuration file. Refer to [Service] section of the /usr/lib/systemd/system/auditd.service configuration file for further details.

Government networks often have substantial auditing requirements and auditd can be configured to meet these requirements. Examining some example audit records demonstrates how the Linux audit system satisfies common requirements. The following example from Fedora Documentation available at https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages shows the substantial amount of information captured in a two typical "raw" audit messages, followed by a breakdown of the most important fields. In this example the message is SELinux-related and reports an AVC denial (and the associated system call) that occurred when the Apache HTTP Server attempted to access the /var/www/html/file1 file (labeled with the samba_share_t type):
type=AVC msg=audit(1226874073.147:96): avc:  denied  { getattr } for pid=2465 comm="httpd"
path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file

type=SYSCALL msg=audit(1226874073.147:96): arch=40000003 syscall=196 success=no exit=-13
a0=b98df198 a1=bfec85dc a2=54dff4 a3=2008171 items=0 ppid=2463 pid=2465 auid=502 uid=48
gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=6 comm="httpd"
exe="/usr/sbin/httpd" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
  • msg=audit(1226874073.147:96)
    • The number in parentheses is the unformatted time stamp (Epoch time) for the event, which can be converted to standard time by using the date command.
  • { getattr }
    • The item in braces indicates the permission that was denied. getattr indicates the source process was trying to read the target file's status information. This occurs before reading files. This action is denied due to the file being accessed having the wrong label. Commonly seen permissions include getattr, read, and write.
  • comm="httpd"
    • The executable that launched the process. The full path of the executable is found in the exe= section of the system call (SYSCALL) message, which in this case, is exe="/usr/sbin/httpd".
  • path="/var/www/html/file1"
    • The path to the object (target) the process attempted to access.
  • scontext="unconfined_u:system_r:httpd_t:s0"
    • The SELinux context of the process that attempted the denied action. In this case, it is the SELinux context of the Apache HTTP Server, which is running in the httpd_t domain.
  • tcontext="unconfined_u:object_r:samba_share_t:s0"
    • The SELinux context of the object (target) the process attempted to access. In this case, it is the SELinux context of file1. Note: the samba_share_t type is not accessible to processes running in the httpd_t domain.
  • From the system call (SYSCALL) message, two items are of interest:
    • success=no: indicates whether the denial (AVC) was enforced or not. success=no indicates the system call was not successful (SELinux denied access). success=yes indicates the system call was successful - this can be seen for permissive domains or unconfined domains, such as initrc_t and kernel_t.
    • exe="/usr/sbin/httpd": the full path to the executable that launched the process, which in this case, is exe="/usr/sbin/httpd".

contains 3 rules

Configure auditd Rules for Comprehensive Auditing   [ref]group

The auditd program can perform comprehensive monitoring of system activity. This section describes recommended configuration settings for comprehensive auditing, but a full description of the auditing system's capabilities is beyond the scope of this guide. The mailing list linux-audit@redhat.com exists to facilitate community discussion of the auditing system.

The audit subsystem supports extensive collection of events, including:

  • Tracing of arbitrary system calls (identified by name or number) on entry or exit.
  • Filtering by PID, UID, call success, system call argument (with some limitations), etc.
  • Monitoring of specific files for modifications to the file's contents or metadata.

Auditing rules at startup are controlled by the file /etc/audit/audit.rules. Add rules to it to meet the auditing requirements for your organization. Each line in /etc/audit/audit.rules represents a series of arguments that can be passed to auditctl and can be individually tested during runtime. See documentation in /usr/share/doc/audit-VERSION and in the related man pages for more details.

If copying any example audit rulesets from /usr/share/doc/audit-VERSION, be sure to comment out the lines containing arch= which are not appropriate for your system's architecture. Then review and understand the following rules, ensuring rules are activated as needed for the appropriate architecture.

After reviewing all the rules, reading the following sections, and editing as needed, the new rules can be activated as follows:
$ sudo service auditd restart

contains 1 rule

Make the auditd Configuration Immutable   [ref]rule

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d in order to make the auditd configuration immutable:

-e 2
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file in order to make the auditd configuration immutable:
-e 2
With this setting, a reboot will be required to change any audit rules.

Rationale:

Making the audit configuration immutable prevents accidental as well as malicious modification of the audit rules, although it may be problematic if legitimate changes are needed during system operation

Severity:  medium

Identifiers:  CCE-27097-5

References:  AC-6, AU-1(b), AU-2(a), AU-2(c), AU-2(d), IR-5, Req-10.5.2, 4.1.18, 5.4.1.1, 3.3.1, 3.4.3

Remediation Shell script:   (show)


# Traverse all of:
#
# /etc/audit/audit.rules,			(for auditctl case)
# /etc/audit/rules.d/*.rules			(for augenrules case)
#
# files to check if '-e .*' setting is present in that '*.rules' file already.
# If found, delete such occurrence since auditctl(8) manual page instructs the
# '-e 2' rule should be placed as the last rule in the configuration
find /etc/audit /etc/audit/rules.d -maxdepth 1 -type f -name *.rules -exec sed -i '/-e[[:space:]]\+.*/d' {} ';'

# Append '-e 2' requirement at the end of both:
# * /etc/audit/audit.rules file 		(for auditctl case)
# * /etc/audit/rules.d/immutable.rules		(for augenrules case)

for AUDIT_FILE in "/etc/audit/audit.rules" "/etc/audit/rules.d/immutable.rules"
do
	echo '' >> $AUDIT_FILE
	echo '# Set the audit.rules configuration immutable per security requirements' >> $AUDIT_FILE
	echo '# Reboot is required to change audit rules once this setting is applied' >> $AUDIT_FILE
	echo '-e 2' >> $AUDIT_FILE
done

Enable auditd Service   [ref]rule

The auditd service is an essential userspace component of the Linux Auditing System, as it is responsible for writing audit records to disk. The auditd service can be enabled with the following command:

$ sudo systemctl enable auditd.service

Rationale:

Without establishing what type of events occurred, it would be difficult to establish, correlate, and investigate the events leading up to an outage or attack. Ensuring the auditd service is active ensures audit records generated by the kernel are appropriately recorded.

Additionally, a properly configured audit subsystem ensures that actions of individual system users can be uniquely traced to those users so they can be held accountable for their actions.

Severity:  high

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:enable
# Function to enable/disable and start/stop services on RHEL and Fedora systems.
#
# Example Call(s):
#
#     service_command enable bluetooth
#     service_command disable bluetooth.service
#
#     Using xinetd:
#     service_command disable rsh.socket xinetd=rsh
#
function service_command {

# Load function arguments into local variables
local service_state=$1
local service=$2
local xinetd=$(echo $3 | cut -d'=' -f2)

# Check sanity of the input
if [ $# -lt "2" ]
then
  echo "Usage: service_command 'enable/disable' 'service_name.service'"
  echo
  echo "To enable or disable xinetd services add \'xinetd=service_name\'"
  echo "as the last argument"  
  echo "Aborting."
  exit 1
fi

# If systemctl is installed, use systemctl command; otherwise, use the service/chkconfig commands
if [ -f "/usr/bin/systemctl" ] ; then
  service_util="/usr/bin/systemctl"
else
  service_util="/sbin/service"
  chkconfig_util="/sbin/chkconfig"
fi

# If disable is not specified in arg1, set variables to enable services.
# Otherwise, variables are to be set to disable services.
if [ "$service_state" != 'disable' ] ; then
  service_state="enable"
  service_operation="start"
  chkconfig_state="on"
else
  service_state="disable"
  service_operation="stop"
  chkconfig_state="off"
fi

# If chkconfig_util is not empty, use chkconfig/service commands.
if ! [ "x$chkconfig_util" = x ] ; then
  $service_util $service $service_operation
  $chkconfig_util --level 0123456 $service $chkconfig_state
else
  $service_util $service_operation $service
  $service_util $service_state $service
fi

# Test if local variable xinetd is empty using non-bashism.
# If empty, then xinetd is not being used.
if ! [ "x$xinetd" = x ] ; then
  grep -qi disable /etc/xinetd.d/$xinetd && \

  if ! [ "$service_operation" != 'disable' ] ; then
    sed -i "s/disable.*/disable         = no/gI" /etc/xinetd.d/$xinetd
  else
    sed -i "s/disable.*/disable         = yes/gI" /etc/xinetd.d/$xinetd
  fi
fi

}

service_command enable auditd
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
- name: "Enable service auditd"
  service:
    name="{{item}}"
    enabled="yes"
    state="started"
  with_items:
    - auditd
  tags:
    - service_auditd_enabled
    - high_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - CCE-27407-6
    - NIST-800-53-AU-3
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-1(b)
    - NIST-800-53-AU-10
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-IR-5
    - NIST-800-171-3.3.1
    - NIST-800-171-3.3.2
    - NIST-800-171-3.3.6
    - PCI-DSS-Req-10
    - CJIS-5.4.1.1

Enable Auditing for Processes Which Start Prior to the Audit Daemon   [ref]rule

To ensure all processes can be audited, even those which start prior to the audit daemon, add the argument audit=1 to the default GRUB 2 command line for the Linux operating system in /etc/default/grub, in the manner below:

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=VolGroup/LogVol06 rd.lvm.lv=VolGroup/lv_swap rhgb quiet rd.shell=0 audit=1"

Warning:  The GRUB 2 configuration file, grub.cfg, is automatically updated each time a new kernel is installed. Note that any changes to /etc/default/grub require rebuilding the grub.cfg file. To update the GRUB 2 configuration file manually, use the
grub2-mkconfig -o
command as follows:
  • On BIOS-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
  • On UEFI-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
Rationale:

Each process on the system carries an "auditable" flag which indicates whether its activities can be audited. Although auditd takes care of enabling this for all processes which launch after it does, adding the kernel argument ensures it is set for every process during boot.

Severity:  medium

Identifiers:  CCE-27212-0

References:  AC-17(1), AU-14(1), AU-1(b), AU-2(a), AU-2(c), AU-2(d), AU-10, IR-5, 1464, 130, Req-10.3, 4.1.3, 5.4.1.1, 3.3.1

Remediation Shell script:   (show)


# Correct the form of default kernel command line in /etc/default/grub
grep -q ^GRUB_CMDLINE_LINUX=\".*audit=0.*\" /etc/default/grub && \
  sed -i "s/audit=[^[:space:]\+]/audit=1/g" /etc/default/grub
if ! [ $? -eq 0 ]; then
  sed -i "s/\(GRUB_CMDLINE_LINUX=\)\"\(.*\)\"/\1\"\2 audit=1\"/" /etc/default/grub
fi

# Correct the form of kernel command line for each installed kernel
# in the bootloader
/sbin/grubby --update-kernel=ALL --args="audit=1"
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: "Enable Auditing for Processes Which Start Prior to the Audit Daemon"
  shell: /sbin/grubby --update-kernel=ALL --args="audit=1"
  tags:
    - bootloader_audit_argument
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27212-0
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-AU-1(b)
    - NIST-800-53-AU-2(a)
    - NIST-800-53-AU-2(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-10
    - NIST-800-53-IR-5
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.3
    - CJIS-5.4.1.1

Services   [ref]group

The best protection against vulnerable software is running less software. This section describes how to review the software which Red Hat Enterprise Linux 7 installs on a system and disable software which is not needed. It then enumerates the software packages installed on a default Red Hat Enterprise Linux 7 system and provides guidance about which ones can be safely disabled.

Red Hat Enterprise Linux 7 provides a convenient minimal install option that essentially installs the bare necessities for a functional system. When building Red Hat Enterprise Linux 7 systems, it is highly recommended to select the minimal packages and then build up the system from there.

contains 10 rules

Base Services   [ref]group

This section addresses the base services that are installed on a Red Hat Enterprise Linux 7 default installation which are not covered in other sections. Some of these services listen on the network and should be treated with particular discretion. Other services are local system utilities that may or may not be extraneous. In general, system services should be disabled if not required.

contains 1 rule

Disable Red Hat Network Service (rhnsd)   [ref]rule

The Red Hat Network service automatically queries Red Hat Network servers to determine whether there are any actions that should be executed, such as package updates. This only occurs if the system was registered to an RHN server or satellite and managed as such. The rhnsd service can be disabled with the following command:

$ sudo systemctl disable rhnsd.service

Rationale:

Although systems management and patching is extremely important to system security, management by a system outside the enterprise enclave is not desirable for some environments. However, if the system is being managed by RHN or RHN Satellite Server the rhnsd daemon can remain on.

Severity:  low

Identifiers:  CCE-80269-4

References:  AC-17(8), CM-7, 382, 1.2.5

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:disable
# Function to enable/disable and start/stop services on RHEL and Fedora systems.
#
# Example Call(s):
#
#     service_command enable bluetooth
#     service_command disable bluetooth.service
#
#     Using xinetd:
#     service_command disable rsh.socket xinetd=rsh
#
function service_command {

# Load function arguments into local variables
local service_state=$1
local service=$2
local xinetd=$(echo $3 | cut -d'=' -f2)

# Check sanity of the input
if [ $# -lt "2" ]
then
  echo "Usage: service_command 'enable/disable' 'service_name.service'"
  echo
  echo "To enable or disable xinetd services add \'xinetd=service_name\'"
  echo "as the last argument"  
  echo "Aborting."
  exit 1
fi

# If systemctl is installed, use systemctl command; otherwise, use the service/chkconfig commands
if [ -f "/usr/bin/systemctl" ] ; then
  service_util="/usr/bin/systemctl"
else
  service_util="/sbin/service"
  chkconfig_util="/sbin/chkconfig"
fi

# If disable is not specified in arg1, set variables to enable services.
# Otherwise, variables are to be set to disable services.
if [ "$service_state" != 'disable' ] ; then
  service_state="enable"
  service_operation="start"
  chkconfig_state="on"
else
  service_state="disable"
  service_operation="stop"
  chkconfig_state="off"
fi

# If chkconfig_util is not empty, use chkconfig/service commands.
if ! [ "x$chkconfig_util" = x ] ; then
  $service_util $service $service_operation
  $chkconfig_util --level 0123456 $service $chkconfig_state
else
  $service_util $service_operation $service
  $service_util $service_state $service
fi

# Test if local variable xinetd is empty using non-bashism.
# If empty, then xinetd is not being used.
if ! [ "x$xinetd" = x ] ; then
  grep -qi disable /etc/xinetd.d/$xinetd && \

  if ! [ "$service_operation" != 'disable' ] ; then
    sed -i "s/disable.*/disable         = no/gI" /etc/xinetd.d/$xinetd
  else
    sed -i "s/disable.*/disable         = yes/gI" /etc/xinetd.d/$xinetd
  fi
fi

}

service_command disable rhnsd
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:disable
- name: "Disable service rhnsd"
  service:
    name="{{item}}"
    enabled="no"
    state="stopped"
  with_items:
    - rhnsd
  tags:
    - service_rhnsd_disabled
    - low_severity
    - disable_strategy
    - low_complexity
    - low_disruption
    - CCE-80269-4
    - NIST-800-53-AC-17(8)
    - NIST-800-53-CM-7

Cron and At Daemons   [ref]group

The cron and at services are used to allow commands to be executed at a later time. The cron service is required by almost all systems to perform necessary maintenance tasks, while at may or may not be required on a given system. Both daemons should be configured defensively.

contains 1 rule

Enable cron Service   [ref]rule

The crond service is used to execute commands at preconfigured times. It is required by almost all systems to perform necessary maintenance tasks, such as notifying root of system activity. The crond service can be enabled with the following command:

$ sudo systemctl enable crond.service

Rationale:

Due to its usage for maintenance and security-supporting tasks, enabling the cron daemon is essential.

Severity:  medium

Identifiers:  CCE-27323-5

References:  CM-7, 5.1.1

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:enable
# Function to enable/disable and start/stop services on RHEL and Fedora systems.
#
# Example Call(s):
#
#     service_command enable bluetooth
#     service_command disable bluetooth.service
#
#     Using xinetd:
#     service_command disable rsh.socket xinetd=rsh
#
function service_command {

# Load function arguments into local variables
local service_state=$1
local service=$2
local xinetd=$(echo $3 | cut -d'=' -f2)

# Check sanity of the input
if [ $# -lt "2" ]
then
  echo "Usage: service_command 'enable/disable' 'service_name.service'"
  echo
  echo "To enable or disable xinetd services add \'xinetd=service_name\'"
  echo "as the last argument"  
  echo "Aborting."
  exit 1
fi

# If systemctl is installed, use systemctl command; otherwise, use the service/chkconfig commands
if [ -f "/usr/bin/systemctl" ] ; then
  service_util="/usr/bin/systemctl"
else
  service_util="/sbin/service"
  chkconfig_util="/sbin/chkconfig"
fi

# If disable is not specified in arg1, set variables to enable services.
# Otherwise, variables are to be set to disable services.
if [ "$service_state" != 'disable' ] ; then
  service_state="enable"
  service_operation="start"
  chkconfig_state="on"
else
  service_state="disable"
  service_operation="stop"
  chkconfig_state="off"
fi

# If chkconfig_util is not empty, use chkconfig/service commands.
if ! [ "x$chkconfig_util" = x ] ; then
  $service_util $service $service_operation
  $chkconfig_util --level 0123456 $service $chkconfig_state
else
  $service_util $service_operation $service
  $service_util $service_state $service
fi

# Test if local variable xinetd is empty using non-bashism.
# If empty, then xinetd is not being used.
if ! [ "x$xinetd" = x ] ; then
  grep -qi disable /etc/xinetd.d/$xinetd && \

  if ! [ "$service_operation" != 'disable' ] ; then
    sed -i "s/disable.*/disable         = no/gI" /etc/xinetd.d/$xinetd
  else
    sed -i "s/disable.*/disable         = yes/gI" /etc/xinetd.d/$xinetd
  fi
fi

}

service_command enable crond
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:enable
- name: "Enable service crond"
  service:
    name="{{item}}"
    enabled="yes"
    state="started"
  with_items:
    - crond
  tags:
    - service_crond_enabled
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - CCE-27323-5
    - NIST-800-53-CM-7

SSH Server   [ref]group

The SSH protocol is recommended for remote login and remote file transfer. SSH provides confidentiality and integrity for data exchanged between two systems, as well as server authentication, through the use of public key cryptography. The implementation included with the system is called OpenSSH, and more detailed documentation is available from its website, http://www.openssh.org. Its server program is called sshd and provided by the RPM package openssh-server.

contains 8 rules

Configure OpenSSH Server if Necessary   [ref]group

If the system needs to act as an SSH server, then certain changes should be made to the OpenSSH daemon configuration file /etc/ssh/sshd_config. The following recommendations can be applied to this file. See the sshd_config(5) man page for more detailed information.

contains 8 rules

Allow Only SSH Protocol 2   [ref]rule

Only SSH protocol version 2 connections should be permitted. The default setting in /etc/ssh/sshd_config is correct, and can be verified by ensuring that the following line appears:

Protocol 2

Rationale:

SSH protocol version 1 is an insecure implementation of the SSH protocol and has many well-known vulnerability exploits. Exploits of the SSH daemon could provide immediate root access to the system.

Severity:  high

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/ssh/sshd_config' '^Protocol' '2' 'CCE-27320-1' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Allow Only SSH Protocol 2"
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^Protocol [0-9]"
    line: "Protocol 2"
    validate: sshd -t -f %s
  #notify: :reload ssh
  tags:
    - sshd_allow_only_protocol2
    - high_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27320-1
    - NIST-800-53-AC-17(8).1(ii)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-171-3.1.13
    - NIST-800-171-3.5.4
    - CJIS-5.5.6

Set LogLevel to INFO   [ref]rule

The INFO parameter specifices that record login and logout activity will be logged. To specify the log level in SSH, add or correct the following line in the /etc/ssh/sshd_config file:

LogLevel INFO

Rationale:

SSH provides several logging levels with varying amounts of verbosity. DEBUG is specifically not recommended other than strictly for debugging SSH communications since it provides so much data that it is difficult to identify important security information. INFO level is the basic level that only records login activity of SSH users. In many situations, such as Incident Response, it is important to determine when a particular user was active on a system. The logout record can eliminate those users who disconnected, which helps narrow the field.

Severity:  low

References:  5.2.3

Disable Host-Based Authentication   [ref]rule

SSH's cryptographic host-based authentication is more secure than .rhosts authentication. However, it is not recommended that hosts unilaterally trust one another, even within an organization.

To disable host-based authentication, add or correct the following line in /etc/ssh/sshd_config:

HostbasedAuthentication no

Rationale:

SSH trust relationships mean a compromise on one host can allow an attacker to move trivially to other hosts.

Severity:  medium

Identifiers:  CCE-27413-4

References:  RHEL-07-010470, AC-3, CM-6(b), 366, SRG-OS-000480-GPOS-00229, 5.2.7, 5.5.6, 3.1.12

Remediation Shell script:   (show)

grep -q ^HostbasedAuthentication /etc/ssh/sshd_config && \
  sed -i "s/HostbasedAuthentication.*/HostbasedAuthentication no/g" /etc/ssh/sshd_config
if ! [ $? -eq 0 ]; then
    echo "HostbasedAuthentication no" >> /etc/ssh/sshd_config
fi
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Disable Host-Based Authentication
  lineinfile:
    create: yes
    dest: /etc/ssh/sshd_config
    regexp: ^HostbasedAuthentication
    line: HostbasedAuthentication no
  tags:
    - disable_host_auth
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27413-4
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(b)
    - NIST-800-171-3.1.12
    - CJIS-5.5.6

Disable SSH Access via Empty Passwords   [ref]rule

To explicitly disallow SSH login from accounts with empty passwords, add or correct the following line in /etc/ssh/sshd_config:

PermitEmptyPasswords no

Any accounts with empty passwords should be disabled immediately, and PAM configuration should prevent users from being able to assign themselves empty passwords.

Rationale:

Configuring this setting for the SSH daemon provides additional assurance that remote login via SSH will require a password, even in the event of misconfiguration elsewhere.

Severity:  high

Identifiers:  CCE-27471-2

References:  RHEL-07-010300, AC-3, AC-6, CM-6(b), 366, SRG-OS-000480-GPOS-00229, 5.5.6, 3.1.1, 3.1.5, 5.2.9

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/ssh/sshd_config' '^PermitEmptyPasswords' 'no' 'CCE-27471-2' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Diable SSH Access via Empty Passwords
  lineinfile:
    create: yes
    dest: /etc/ssh/sshd_config
    regexp: ^PermitEmptyPasswords
    line: PermitEmptyPasswords no
    validate: sshd -t -f %s
  tags:
    - sshd_disable_empty_passwords
    - high_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27471-2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(b)
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - CJIS-5.5.6

Enable SSH Warning Banner   [ref]rule

To enable the warning banner and ensure it is consistent across the system, add or correct the following line in /etc/ssh/sshd_config:

Banner /etc/issue
Another section contains information on how to create an appropriate system-wide warning banner.

Rationale:

The warning message reinforces policy awareness during the logon process and facilitates possible legal action against attackers. Alternatively, systems whose ownership should not be obvious should ensure usage of a banner that does not provide easy attribution.

Severity:  medium

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/ssh/sshd_config' '^Banner' '/etc/issue' 'CCE-27314-4' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Enable SSH Warning Banner
  lineinfile:
    create: yes
    dest: /etc/ssh/sshd_config
    regexp: ^Banner
    line: Banner /etc/issue
    validate: sshd -t -f %s
  tags:
    - sshd_enable_warning_banner
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27314-4
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)(1)
    - NIST-800-53-AC-8(c)(2)
    - NIST-800-53-AC-8(c)(3)
    - NIST-800-171-3.1.9
    - CJIS-5.5.6

Do Not Allow SSH Environment Options   [ref]rule

To ensure users are not able to override environment options to the SSH daemon, add or correct the following line in /etc/ssh/sshd_config:

PermitUserEnvironment no

Rationale:

SSH environment options potentially allow users to bypass access restriction in some configurations.

Severity:  medium

Identifiers:  CCE-27363-1

References:  RHEL-07-010460, CM-6(b), 366, SRG-OS-000480-GPOS-00229, 5.2.10, 5.5.6, 3.1.12

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/ssh/sshd_config' '^PermitUserEnvironment' 'no' 'CCE-27363-1' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Do Not Allow SSH Environment Options
  lineinfile:
    create: yes
    dest: /etc/ssh/sshd_config
    regexp: ^PermitUserEnvironment
    line: PermitUserEnvironment no
    validate: sshd -t -f %s
  tags:
    - sshd_do_not_permit_user_env
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27363-1
    - NIST-800-53-CM-6(b)
    - NIST-800-171-3.1.12
    - CJIS-5.5.6

Use Only FIPS 140-2 Validated Ciphers   [ref]rule

Limit the ciphers to those algorithms which are FIPS-approved. Counter (CTR) mode is also preferred over cipher-block chaining (CBC) mode. The following line in /etc/ssh/sshd_config demonstrates use of FIPS 140-2 validated ciphers:

Ciphers aes128-ctr,aes192-ctr,aes256-ctr


The following ciphers are FIPS 140-2 certified on RHEL 7:
- aes128-ctr
- aes192-ctr
- aes256-ctr
- aes128-cbc
- aes192-cbc
- aes256-cbc
- 3des-cbc
- rijndael-cbc@lysator.liu.se

Any combination of the above ciphers will pass this check. Official FIPS 140-2 paperwork for RHEL7 can be found at http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2630.pdf.

Rationale:

Unapproved mechanisms that are used for authentication to the cryptographic module are not verified and therefore cannot be relied upon to provide confidentiality or integrity, and system data may be compromised.
Operating systems utilizing encryption are required to use FIPS-compliant mechanisms for authenticating to cryptographic modules.
FIPS 140-2 is the current standard for validating that mechanisms used to access cryptographic modules utilize authentication that meets industry and government requirements. For government systems, this allows Security Levels 1, 2, 3, or 4 for use on Red Hat Enterprise Linux.

Severity:  medium

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects four 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
#
# 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 config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  # Check sanity of the input
  if [ $# -lt "3" ]
  then
        echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
        echo
        echo "If symlinks need to be taken into account, add yes/no to the last argument"
        echo "to allow to 'follow_symlinks'."
        echo "Aborting."
        exit 1
  fi

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  if test -L $config_file; then
    sed_command="sed -i --follow-symlinks"
  else
    sed_command="sed -i"
  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 ! [ "x$cce" = x ] && [ "$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)

  # If there is no print format specified in the last arg, use the default format.
  if ! [ "x$format" = x ] ; then
    printf -v formatted_output "$format" "$stripped_key" "$value"
  else
    formatted_output="$stripped_key = $value"
  fi

  # If the key exists, change it. Otherwise, add it to the config_file.
  if `grep -qi "$key" $config_file` ; then
    eval '$sed_command "s/$key.*/$formatted_output/g" $config_file'
  else
    # \n is precaution for case where file ends without trailing newline
    echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
    echo -e "$formatted_output" >> $config_file
  fi

}

replace_or_append '/etc/ssh/sshd_config' '^Ciphers' 'aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc' 'CCE-27295-5' '%s %s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: Use Only Approved Ciphers
  lineinfile:
    create: yes
    dest: /etc/ssh/sshd_config
    regexp: ^Ciphers
    line: Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc
    validate: sshd -t -f %s
  #notify: restart sshd
  tags:
    - sshd_use_approved_ciphers
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - CCE-27295-5
    - NIST-800-53-AC-3
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AU-10(5)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-7
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - CJIS-5.5.6
Red Hat and Red Hat Enterprise Linux are either registered trademarks or trademarks of Red Hat, Inc. in the United States and other countries. All other names are registered trademarks or trademarks of their respective companies.