System Settings
[ref]groupContains rules that check correct system settings. |
SELinux
[ref]groupSELinux 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
|
Ensure SELinux Not Disabled in /etc/default/grub
[ref]ruleSELinux 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.
References:
AC-3, AC-3(3), AC-3(4), AC-4, AC-6, AU-9, SI-6(a), CCI-000022, CCI-000032, 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]ruleThe 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.
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: XCCDF Value var_selinux_state # promote to variable
set_fact:
var_selinux_state: enforcing
tags:
- always
- name: "Ensure SELinux State is Enforcing"
lineinfile:
path: /etc/sysconfig/selinux
regexp: '^SELINUX='
line: "SELINUX={{ var_selinux_state }}"
create: yes
tags:
- selinux_state
- high_severity
- restrict_strategy
- low_complexity
- low_disruption
- CCE-27334-2
- DISA-STIG-RHEL-07-020210
|
Configure SELinux Policy
[ref]ruleThe 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 .
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: XCCDF Value var_selinux_policy_name # promote to variable
set_fact:
var_selinux_policy_name: targeted
tags:
- always
- name: "Configure SELinux Policy"
lineinfile:
path: /etc/sysconfig/selinux
regexp: '^SELINUXTYPE='
line: "SELINUXTYPE={{ var_selinux_policy_name }}"
create: yes
tags:
- selinux_policytype
- high_severity
- restrict_strategy
- low_complexity
- low_disruption
- CCE-27279-9
- DISA-STIG-RHEL-07-020220
|
Ensure SELinux support is enabled in Docker
[ref]rule
To enable the SELinux for the Docker service, the Docker service must be
configured to run the Docker daemon with --selinux-enabled option.
In /etc/sysconfig/docker configuration file, add or correct
the following line to enable SELinux support in the Docker daemon:
OPTIONS='--selinux-enabled'
Rationale:
If SELinux is not explicitely enabled in the Docker daemon configuration,
Docker does not use SELinux which means Docker runs unconfined,
and SELinux will not provide security separation for Docker container
processes. However enabling SELinux for the Docker service prevents
an attacker or rogue container from attacking other container processes
and content as well as prevents taking over the host operating system.
|
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.
|
Docker Service
[ref]group
The docker service is necessary to create containers, which are
self-sufficient and self-contained applications using the resource
isolation features of the kernel.
|
Enable the Docker service
[ref]ruleThe docker service is commonly needed to
create containers.
The docker service can be enabled with the following command:
$ sudo systemctl enable docker.service
Rationale:
To be able to find any problems with misconfiguration of
the docker daemon and running containers, the docker service
has to be enabled.
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 docker
Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Strategy: | enable |
---|
- name: Enable service docker
service:
name="{{item}}"
enabled="yes"
state="started"
with_items:
- docker
tags:
- service_docker_enabled
- medium_severity
- enable_strategy
- low_complexity
- low_disruption
- CCE-80440-1
|
Use direct-lvm with the Device Mapper Storage Driver
[ref]rule
To use Docker in production with the device mapper storage driver, the Docker
daemon should be configured to use direct-lvm instead of loopback device as
a storage. For setting up the LVM and configuring Docker, see the
Docker Device Mapper Storage Documentation.
Rationale:
For using Docker in production, the device mapper storage driver with loopback
devices is discouraged. The suggested way of configuring device mapper storage
driver is direct-lvm. Choosing the right storage driver and backing filesystem
is crucial to stability and performance.
|