Guide to the Secure Configuration of Red Hat Enterprise Linux 8

with profile PCI-DSS v3.2.1 Control Baseline for Red Hat Enterprise Linux 8
Ensures PCI-DSS v3.2.1 security configuration settings are applied.
This guide presents a catalog of security-relevant configuration settings for Red Hat Enterprise Linux 8. 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, 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.

Evaluation Characteristics

Evaluation targetrhel8.example.com
Benchmark URLssg-rhel8-ds.xml
Benchmark IDxccdf_org.ssgproject.content_benchmark_RHEL-8
Benchmark version0.1.50
Profile IDxccdf_org.ssgproject.content_profile_pci-dss
Started at2021-03-21T20:15:13+01:00
Finished at2021-03-21T20:15:53+01:00
Performed byroot
Test systemcpe:/a:redhat:openscap:1.3.3

CPE Platforms

  • cpe:/o:redhat:enterprise_linux:8

Addresses

  • IPv4  127.0.0.1
  • IPv4  192.168.122.8
  • IPv6  0:0:0:0:0:0:0:1
  • IPv6  fe80:0:0:0:9fb8:54a0:643b:ab20
  • MAC  00:00:00:00:00:00
  • MAC  52:54:00:E6:B4:A4

Compliance and Scoring

The target system did not satisfy the conditions of 73 rules! Please review rule results and consider applying remediation.

Rule results

43 passed
73 failed
1 other

Severity of failed rules

0 other
0 low
70 medium
3 high

Score

Scoring systemScoreMaximumPercent
urn:xccdf:scoring:default62.564674100.000000
62.56%

Rule Overview

Group rules by:
TitleSeverityResult
Guide to the Secure Configuration of Red Hat Enterprise Linux 8 73x fail 1x notchecked
System Settings 71x fail 1x notchecked
Account and Access Control 15x fail
Protect Accounts by Configuring PAM 7x fail
Set Password Quality Requirements 4x fail
Set Password Quality Requirements with pam_pwquality 4x fail
Ensure PAM Enforces Password Requirements - Minimum Uppercase Charactersmedium
fail
Ensure PAM Enforces Password Requirements - Minimum Lowercase Charactersmedium
fail
Ensure PAM Enforces Password Requirements - Minimum Lengthmedium
fail
Ensure PAM Enforces Password Requirements - Minimum Digit Charactersmedium
fail
Set Password Hashing Algorithm
Set Password Hashing Algorithm in /etc/login.defsmedium
pass
Set Password Hashing Algorithm in /etc/libuser.confmedium
pass
Set PAM's Password Hashing Algorithmmedium
pass
Set Lockouts for Failed Password Attempts 3x fail
Set Lockout Time for Failed Password Attemptsmedium
fail
Set Deny For Failed Password Attemptsmedium
fail
Limit Password Reusemedium
fail
Protect Physical Console Access 5x fail
Configure Screen Locking 5x fail
Install the opensc Package For Multifactor Authenticationmedium
fail
Install the pcsc-lite packagemedium
fail
Enable the pcscd Servicemedium
fail
Configure opensc Smart Card Driversmedium
fail
Force opensc To Use Defined Smart Card Drivermedium
fail
Protect Accounts by Restricting Password-Based Login 3x fail
Verify Proper Storage and Existence of Password Hashes 1x fail
Verify All Account Password Hashes are Shadowedmedium
pass
All GIDs referenced in /etc/passwd must be defined in /etc/grouplow
pass
Prevent Login to Accounts With Empty Passwordhigh
fail
Set Account Expiration Following Inactivitymedium
fail
Set Password Expiration Parameters 1x fail
Set Password Maximum Agemedium
fail
System Accounting with auditd 50x fail
Configure auditd Rules for Comprehensive Auditing 45x fail
Record Unauthorized Access Attempts Events to Files (unsuccessful) 6x fail
Record Unsuccessful Access Attempts to Files - openmedium
fail
Record Unsuccessful Access Attempts to Files - truncatemedium
fail
Record Unsuccessful Access Attempts to Files - creatmedium
fail
Record Unsuccessful Access Attempts to Files - open_by_handle_atmedium
fail
Record Unsuccessful Access Attempts to Files - openatmedium
fail
Record Unsuccessful Access Attempts to Files - ftruncatemedium
fail
Record Information on Kernel Modules Loading and Unloading 3x fail
Ensure auditd Collects Information on Kernel Module Loading and Unloading - finit_modulemedium
fail
Ensure auditd Collects Information on Kernel Module Loading - init_modulemedium
fail
Ensure auditd Collects Information on Kernel Module Unloading - delete_modulemedium
fail
Record Events that Modify the System's Discretionary Access Controls 13x fail
Record Events that Modify the System's Discretionary Access Controls - lchownmedium
fail
Record Events that Modify the System's Discretionary Access Controls - setxattrmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fchownmedium
fail
Record Events that Modify the System's Discretionary Access Controls - chownmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fchownatmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fremovexattrmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fsetxattrmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fchmodatmedium
fail
Record Events that Modify the System's Discretionary Access Controls - lsetxattrmedium
fail
Record Events that Modify the System's Discretionary Access Controls - removexattrmedium
fail
Record Events that Modify the System's Discretionary Access Controls - chmodmedium
fail
Record Events that Modify the System's Discretionary Access Controls - fchmodmedium
fail
Record Events that Modify the System's Discretionary Access Controls - lremovexattrmedium
fail
Record Attempts to Alter Logon and Logout Eventsmedium
fail
Record Information on the Use of Privileged Commands 1x fail
Ensure auditd Collects Information on the Use of Privileged Commandsmedium
fail
Records Events that Modify Date and Time Information 5x fail
Record Attempts to Alter Time Through stimemedium
fail
Record attempts to alter time through adjtimexmedium
fail
Record Attempts to Alter Time Through clock_settimemedium
fail
Record Attempts to Alter the localtime Filemedium
fail
Record attempts to alter time through settimeofdaymedium
fail
Record File Deletion Events by User 5x fail
Ensure auditd Collects File Deletion Events by User - rmdirmedium
fail
Ensure auditd Collects File Deletion Events by User - renamemedium
fail
Ensure auditd Collects File Deletion Events by User - unlinkmedium
fail
Ensure auditd Collects File Deletion Events by User - unlinkatmedium
fail
Ensure auditd Collects File Deletion Events by User - renameatmedium
fail
Ensure auditd Collects Information on Exporting to Media (successful)medium
fail
Record Events that Modify User/Group Information - /etc/gshadowmedium
fail
Record Events that Modify the System's Network Environmentmedium
fail
System Audit Logs Must Be Owned By Rootmedium
pass
Record Events that Modify the System's Mandatory Access Controlsmedium
fail
Record Events that Modify User/Group Information - /etc/shadowmedium
fail
Record Events that Modify User/Group Information - /etc/passwdmedium
fail
Record Events that Modify User/Group Information - /etc/groupmedium
fail
Make the auditd Configuration Immutablemedium
fail
Record Attempts to Alter Process and Session Initiation Informationmedium
fail
Record Events that Modify User/Group Information - /etc/security/opasswdmedium
fail
System Audit Logs Must Have Mode 0640 or Less Permissivemedium
pass
Ensure auditd Collects System Administrator Actionsmedium
fail
Configure auditd Data Retention 3x fail
Configure auditd to use audispd's syslog pluginmedium
fail
Configure auditd space_left Action on Low Disk Spacemedium
fail
Configure auditd mail_acct Action on Low Disk Spacemedium
pass
Configure auditd Max Log File Sizemedium
pass
Configure auditd admin_space_left Action on Low Disk Spacemedium
fail
Configure auditd max_log_file_action Upon Reaching Maximum Log Sizemedium
pass
Configure auditd Number of Logs Retainedmedium
pass
Install audispd-plugins Packagemedium
fail
Enable auditd Servicehigh
pass
Enable Auditing for Processes Which Start Prior to the Audit Daemonmedium
fail
Installing and Maintaining Software 5x fail 1x notchecked
Updating Software 1x fail 1x notchecked
Ensure gpgcheck Enabled In Main yum Configurationhigh
pass
Ensure Red Hat GPG Key Installedhigh
pass
Ensure Software Patches Installed () high
notchecked
Ensure gpgcheck Enabled for All yum Package Repositorieshigh
fail
GNOME Desktop Environment
Configure GNOME Screen Locking
Set GNOME3 Screensaver Inactivity Timeoutmedium
notapplicable
Enable GNOME3 Screensaver Idle Activationmedium
notapplicable
Implement Blank Screensavermedium
notapplicable
Enable GNOME3 Screensaver Lock After Idle Periodmedium
notapplicable
Make sure that the dconf databases are up-to-date with regards to respective keyfileshigh
notapplicable
System and Software Integrity 4x fail
Software Integrity Checking 4x fail
Verify Integrity with AIDE 3x fail
Install AIDEmedium
fail
Configure Periodic Execution of AIDEmedium
fail
Build and Test AIDE Databasemedium
fail
Verify Integrity with RPM 1x fail
Verify File Hashes with RPMhigh
pass
Verify and Correct File Permissions with RPMhigh
fail
System Cryptographic Policies
Configure SSH to use System Crypto Policymedium
pass
Configure BIND to use System Crypto Policymedium
pass
Configure OpenSSL library to use System Crypto Policymedium
pass
Configure Libreswan to use System Crypto Policymedium
pass
Configure System Cryptography Policyhigh
pass
Configure Kerberos to use System Crypto Policymedium
pass
Endpoint Protection Software
Install Intrusion Detection Softwarehigh
pass
GRUB2 bootloader configuration
Verify /boot/grub2/grub.cfg Group Ownershipmedium
pass
Verify /boot/grub2/grub.cfg User Ownershipmedium
pass
Network Configuration and Firewalls
IPSec Support
Install libreswan Packagemedium
pass
Configure Syslog 1x fail
Ensure Proper Configuration of Log Files
Ensure Log Files Are Owned By Appropriate Usermedium
pass
Ensure Log Files Are Owned By Appropriate Groupmedium
pass
Ensure System Log Files Have Correct Permissionsmedium
pass
Ensure All Logs are Rotated by logrotate 1x fail
Ensure Logrotate Runs Periodicallymedium
fail
File Permissions and Masks
Verify Permissions on Important Files and Directories
Verify User Who Owns shadow Filemedium
pass
Verify Permissions on passwd Filemedium
pass
Verify Permissions on shadow Filemedium
pass
Verify Group Who Owns group Filemedium
pass
Verify Group Who Owns passwd Filemedium
pass
Verify Permissions on group Filemedium
pass
Verify User Who Owns passwd Filemedium
pass
Verify User Who Owns group Filemedium
pass
Verify Group Who Owns shadow Filemedium
pass
Services 2x fail
SSH Server 1x fail
Configure OpenSSH Server if Necessary 1x fail
Set SSH Idle Timeout Intervalmedium
fail
System Security Services Daemon
Enable Smartcards in SSSDmedium
pass
Network Time Protocol 1x fail
Enable the NTP Daemonmedium
pass
Specify a Remote NTP Servermedium
pass
Specify Additional Remote NTP Serversmedium
fail

Result Details

Ensure PAM Enforces Password Requirements - Minimum Uppercase Charactersxccdf_org.ssgproject.content_rule_accounts_password_pam_ucredit mediumCCE-80665-3

Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_pam_ucredit
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_pam_ucredit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80665-3

References:  6.3.2, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000192, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_MOF_EXT.1, Req-8.2.3, SRG-OS-000069-GPOS-00037, SRG-OS-000069-VMM-000360

Description

The pam_pwquality module's ucredit= parameter controls requirements for usage of uppercase letters in a password. When set to a negative number, any password will be required to contain that many uppercase characters. When set to a positive number, pam_pwquality will grant +1 additional length credit for each uppercase character. Modify the ucredit setting in /etc/security/pwquality.conf to require the use of an uppercase character in passwords.

Rationale

Use of a complex password helps to increase the time and resources reuiqred to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised.



Complexity:low
Disruption:low
Strategy:restrict
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_password_pam_ucredit="-1"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append '/etc/security/pwquality.conf' '^ucredit' $var_password_pam_ucredit 'CCE-80665-3' '%s = %s'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_ucredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80665-3
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
- name: XCCDF Value var_password_pam_ucredit # promote to variable
  set_fact:
    var_password_pam_ucredit: !!str -1
  tags:
    - always

- name: Ensure PAM variable ucredit is set accordingly
  lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*ucredit
    line: ucredit = {{ var_password_pam_ucredit }}
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_ucredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80665-3
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
OVAL test results details

check the configuration of /etc/pam.d/system-auth  oval:ssg-test_password_pam_pwquality:tst:1  true

Following items have been found on the system:
PathContent
/etc/pam.d/system-auth password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=

check the configuration of /etc/security/pwquality.conf  oval:ssg-test_password_pam_pwquality_ucredit:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_password_pam_pwquality_ucredit:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/security/pwquality.conf^ucredit[\s]*=[\s]*(-?\d+)(?:[\s]|$)1
Ensure PAM Enforces Password Requirements - Minimum Lowercase Charactersxccdf_org.ssgproject.content_rule_accounts_password_pam_lcredit mediumCCE-80655-4

Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_pam_lcredit
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_pam_lcredit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80655-4

References:  1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000193, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_MOF_EXT.1, Req-8.2.3, SRG-OS-000070-GPOS-00038, SRG-OS-000070-VMM-000370

Description

The pam_pwquality module's lcredit parameter controls requirements for usage of lowercase letters in a password. When set to a negative number, any password will be required to contain that many lowercase characters. When set to a positive number, pam_pwquality will grant +1 additional length credit for each lowercase character. Modify the lcredit setting in /etc/security/pwquality.conf to require the use of a lowercase character in passwords.

Rationale

Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possble combinations that need to be tested before the password is compromised. Requiring a minimum number of lowercase characters makes password guessing attacks more difficult by ensuring a larger search space.



Complexity:low
Disruption:low
Strategy:restrict
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_password_pam_lcredit="-1"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append '/etc/security/pwquality.conf' '^lcredit' $var_password_pam_lcredit 'CCE-80655-4' '%s = %s'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_lcredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80655-4
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
- name: XCCDF Value var_password_pam_lcredit # promote to variable
  set_fact:
    var_password_pam_lcredit: !!str -1
  tags:
    - always

- name: Ensure PAM variable lcredit is set accordingly
  lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*lcredit
    line: lcredit = {{ var_password_pam_lcredit }}
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_lcredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80655-4
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
OVAL test results details

check the configuration of /etc/pam.d/system-auth  oval:ssg-test_password_pam_pwquality:tst:1  true

Following items have been found on the system:
PathContent
/etc/pam.d/system-auth password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=

check the configuration of /etc/security/pwquality.conf  oval:ssg-test_password_pam_pwquality_lcredit:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_password_pam_pwquality_lcredit:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/security/pwquality.conf^lcredit[\s]*=[\s]*(-?\d+)(?:[\s]|$)1
Ensure PAM Enforces Password Requirements - Minimum Lengthxccdf_org.ssgproject.content_rule_accounts_password_pam_minlen mediumCCE-80656-2

Ensure PAM Enforces Password Requirements - Minimum Length

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_pam_minlen
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_pam_minlen:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80656-2

References:  6.3.2, 1, 12, 15, 16, 5, 5.6.2.1.1, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000205, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_MOF_EXT.1, Req-8.2.3, SRG-OS-000078-GPOS-00046, SRG-OS-000072-VMM-000390, SRG-OS-000078-VMM-000450

Description

The pam_pwquality module's minlen parameter controls requirements for minimum characters required in a password. Add minlen=7 after pam_pwquality to set minimum password length requirements.

Rationale

The shorter the password, the lower the number of possible combinations that need to be tested before the password is compromised.
Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks. Password length is one factor of several that helps to determine strength and how long it takes to crack a password. Use of more characters in a password helps to exponentially increase the time and/or resources required to compromose the password.



Complexity:low
Disruption:low
Strategy:restrict
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_password_pam_minlen="7"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append '/etc/security/pwquality.conf' '^minlen' $var_password_pam_minlen 'CCE-80656-2' '%s = %s'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_minlen
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80656-2
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
    - CJIS-5.6.2.1.1
- name: XCCDF Value var_password_pam_minlen # promote to variable
  set_fact:
    var_password_pam_minlen: !!str 7
  tags:
    - always

- name: Ensure PAM variable minlen is set accordingly
  lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*minlen
    line: minlen = {{ var_password_pam_minlen }}
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_minlen
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80656-2
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
    - CJIS-5.6.2.1.1
OVAL test results details

check the configuration of /etc/pam.d/system-auth  oval:ssg-test_password_pam_pwquality:tst:1  true

Following items have been found on the system:
PathContent
/etc/pam.d/system-auth password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=

check the configuration of /etc/security/pwquality.conf  oval:ssg-test_password_pam_pwquality_minlen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_password_pam_pwquality_minlen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/security/pwquality.conf^minlen[\s]*=[\s]*(\d+)(?:[\s]|$)1
Ensure PAM Enforces Password Requirements - Minimum Digit Charactersxccdf_org.ssgproject.content_rule_accounts_password_pam_dcredit mediumCCE-80653-9

Ensure PAM Enforces Password Requirements - Minimum Digit Characters

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_pam_dcredit
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_pam_dcredit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80653-9

References:  6.3.2, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000194, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_MOF_EXT.1, Req-8.2.3, SRG-OS-000071-GPOS-00039, SRG-OS-000071-VMM-000380

Description

The pam_pwquality module's dcredit parameter controls requirements for usage of digits in a password. When set to a negative number, any password will be required to contain that many digits. When set to a positive number, pam_pwquality will grant +1 additional length credit for each digit. Modify the dcredit setting in /etc/security/pwquality.conf to require the use of a digit in passwords.

Rationale

Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised. Requiring digits makes password guessing attacks more difficult by ensuring a larger search space.



Complexity:low
Disruption:low
Strategy:restrict
# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_password_pam_dcredit="-1"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append '/etc/security/pwquality.conf' '^dcredit' $var_password_pam_dcredit 'CCE-80653-9' '%s = %s'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_dcredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80653-9
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
- name: XCCDF Value var_password_pam_dcredit # promote to variable
  set_fact:
    var_password_pam_dcredit: !!str -1
  tags:
    - always

- name: Ensure PAM variable dcredit is set accordingly
  lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*dcredit
    line: dcredit = {{ var_password_pam_dcredit }}
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_dcredit
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80653-9
    - NIST-800-53-IA-5(c)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - PCI-DSS-Req-8.2.3
OVAL test results details

check the configuration of /etc/pam.d/system-auth  oval:ssg-test_password_pam_pwquality:tst:1  true

Following items have been found on the system:
PathContent
/etc/pam.d/system-auth password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=

check the configuration of /etc/security/pwquality.conf  oval:ssg-test_password_pam_pwquality_dcredit:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_password_pam_pwquality_dcredit:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/security/pwquality.conf^dcredit[\s]*=[\s]*(-?\d+)(?:[\s]|$)1
Set Password Hashing Algorithm in /etc/login.defsxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_logindefs mediumCCE-80892-3

Set Password Hashing Algorithm in /etc/login.defs

Rule IDxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_logindefs
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-set_password_hashing_algorithm_logindefs:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80892-3

References:  NT28(R32), 6.3.1, 1, 12, 15, 16, 5, 5.6.2.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.13.11, CCI-000196, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(c), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1, SRG-OS-000073-GPOS-00041

Description

In /etc/login.defs, add or correct the following line to ensure the system will use SHA-512 as the hashing algorithm:

ENCRYPT_METHOD SHA512

Rationale

Passwords need to be protected at all times, and encryption is the standard method for protecting passwords. If passwords are not encrypted, they can be plainly read (i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm are no more protected than if they are kept in plain text.

Using a stronger hashing algorithm makes password cracking attacks more difficult.

OVAL test results details

The value of ENCRYPT_METHOD should be set appropriately in /etc/login.defs  oval:ssg-test_etc_login_defs_encrypt_method:tst:1  true

Following items have been found on the system:
Var refValue
oval:ssg-variable_last_encrypt_method_instance_value:var:1SHA512
Set Password Hashing Algorithm in /etc/libuser.confxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_libuserconf mediumCCE-80891-5

Set Password Hashing Algorithm in /etc/libuser.conf

Rule IDxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_libuserconf
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-set_password_hashing_algorithm_libuserconf:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80891-5

References:  1, 12, 15, 16, 5, 5.6.2.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.13.11, CCI-000196, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(c), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1, SRG-OS-000073-GPOS-00041, SRG-OS-000480-VMM-002000

Description

In /etc/libuser.conf, add or correct the following line in its [defaults] section to ensure the system will use the SHA-512 algorithm for password hashing:

crypt_style = sha512

Rationale

Passwords need to be protected at all times, and encryption is the standard method for protecting passwords. If passwords are not encrypted, they can be plainly read (i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm are no more protected than if they are kepy in plain text.

This setting ensures user and group account administration utilities are configured to store only encrypted representations of passwords. Additionally, the crypt_style configuration option ensures the use of a strong hashing algorithm that makes password cracking attacks more difficult.

OVAL test results details

The password hashing algorithm should be set correctly in /etc/libuser.conf  oval:ssg-test_etc_libuser_conf_cryptstyle:tst:1  true

Following items have been found on the system:
PathContent
/etc/libuser.conf crypt_style = sha512
Set PAM's Password Hashing Algorithmxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_systemauth mediumCCE-80893-1

Set PAM's Password Hashing Algorithm

Rule IDxccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_systemauth
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-set_password_hashing_algorithm_systemauth:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80893-1

References:  5.4.4, 1, 12, 15, 16, 5, 5.6.2.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.13.11, CCI-000196, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(c), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1, SRG-OS-000073-GPOS-00041, SRG-OS-000480-VMM-002000

Description

The PAM system service can be configured to only store encrypted representations of passwords. In /etc/pam.d/system-auth, the password section of the file controls which PAM modules execute during a password change. Set the pam_unix.so module in the password section to include the argument sha512, as shown below:

password    sufficient    pam_unix.so sha512 other arguments...

This will help ensure when local users change their passwords, hashes for the new passwords will be generated using the SHA-512 algorithm. This is the default.

Rationale

Passwords need to be protected at all times, and encryption is the standard method for protecting passwords. If passwords are not encrypted, they can be plainly read (i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm are no more protected than if they are kepy in plain text.

This setting ensures user and group account administration utilities are configured to store only encrypted representations of passwords. Additionally, the crypt_style configuration option ensures the use of a strong hashing algorithm that makes password cracking attacks more difficult.

OVAL test results details

check /etc/pam.d/system-auth for correct settings  oval:ssg-test_pam_unix_sha512:tst:1  true

Following items have been found on the system:
PathContent
/etc/pam.d/system-authpassword sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow
Set Lockout Time for Failed Password Attemptsxccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_unlock_time mediumCCE-80670-3

Set Lockout Time for Failed Password Attempts

Rule IDxccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_unlock_time
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_passwords_pam_faillock_unlock_time:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80670-3

References:  5.3.2, 1, 12, 15, 16, 5.5.3, DSS05.04, DSS05.10, DSS06.10, 3.1.8, CCI-000044, CCI-002238, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(b), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.7, SRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005, SRG-OS-000329-VMM-001180

Description

To configure the system to lock out accounts after a number of incorrect login attempts and require an administrator to unlock the account using pam_faillock.so, modify the content of both /etc/pam.d/system-auth and /etc/pam.d/password-auth as follows:

  • add the following line immediately before the pam_unix.so statement in the AUTH section:
    auth required pam_faillock.so preauth silent deny=6 unlock_time=1800 fail_interval=900
  • add the following line immediately after the pam_unix.so statement in the AUTH section:
    auth [default=die] pam_faillock.so authfail deny=6 unlock_time=1800 fail_interval=900
  • add the following line immediately before the pam_unix.so statement in the ACCOUNT section:
    account required pam_faillock.so
If unlock_time is set to 0, manual intervention by an administrator is required to unlock a user.

Rationale

Locking out user accounts after a number of incorrect attempts prevents direct password guessing attacks. Ensuring that an administrator is involved in unlocking locked accounts draws appropriate attention to such situations.



# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_accounts_passwords_pam_faillock_unlock_time="1800"

AUTH_FILES=("/etc/pam.d/system-auth" "/etc/pam.d/password-auth")

for pam_file in "${AUTH_FILES[@]}"
do
    # is auth required pam_faillock.so preauth present?
    if grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*$' "$pam_file" ; then
        # is the option set?
        if grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*'"unlock_time"'=([0-9]*).*$' "$pam_file" ; then
            # just change the value of option to a correct value
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock.so.*preauth.*silent.*\)\('"unlock_time"' *= *\).*/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
        # the option is not set.
        else
            # append the option
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock.so.*preauth.*silent.*/ s/$/ '"unlock_time"'='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
        fi
    # auth required pam_faillock.so preauth is not present, insert the whole line
    else
        sed -i --follow-symlinks '/^auth.*sufficient.*pam_unix.so.*/i auth        required      pam_faillock.so preauth silent '"unlock_time"'='"$var_accounts_passwords_pam_faillock_unlock_time" "$pam_file"
    fi
    # is auth default pam_faillock.so authfail present?
    if grep -qE '^\s*auth\s+(\[default=die\])\s+pam_faillock\.so\s+authfail.*$' "$pam_file" ; then
        # is the option set?
        if grep -qE '^\s*auth\s+(\[default=die\])\s+pam_faillock\.so\s+authfail.*'"unlock_time"'=([0-9]*).*$' "$pam_file" ; then
            # just change the value of option to a correct value
            sed -i --follow-symlinks 's/\(^auth.*[default=die].*pam_faillock.so.*authfail.*\)\('"unlock_time"' *= *\).*/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
        # the option is not set.
        else
            # append the option
            sed -i --follow-symlinks '/^auth.*[default=die].*pam_faillock.so.*authfail.*/ s/$/ '"unlock_time"'='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
        fi
    # auth default pam_faillock.so authfail is not present, insert the whole line
    else
        sed -i --follow-symlinks '/^auth.*sufficient.*pam_unix.so.*/a auth        [default=die] pam_faillock.so authfail '"unlock_time"'='"$var_accounts_passwords_pam_faillock_unlock_time" "$pam_file"
    fi
    if ! grep -qE '^\s*account\s+required\s+pam_faillock\.so.*$' "$pam_file" ; then
        sed -E -i --follow-symlinks '/^\s*account\s*required\s*pam_unix.so/i account     required      pam_faillock.so' "$pam_file"
    fi
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3
- name: XCCDF Value var_accounts_passwords_pam_faillock_unlock_time # promote to variable
  set_fact:
    var_accounts_passwords_pam_faillock_unlock_time: !!str 1800
  tags:
    - always

- name: Add auth pam_faillock preauth unlock_time before pam_unix.so
  pamd:
    name: '{{ item }}'
    type: auth
    control: sufficient
    module_path: pam_unix.so
    new_type: auth
    new_control: required
    new_module_path: pam_faillock.so
    module_arguments: preauth silent unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
      }}
    state: before
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3

- name: Add unlock_time argument to pam_faillock preauth
  pamd:
    name: '{{ item }}'
    type: auth
    control: required
    module_path: pam_faillock.so
    module_arguments: preauth silent unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
      }}
    state: args_present
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3

- name: Add auth pam_faillock authfail unlock_interval after pam_unix.so
  pamd:
    name: '{{ item }}'
    type: auth
    control: sufficient
    module_path: pam_unix.so
    new_type: auth
    new_control: '[default=die]'
    new_module_path: pam_faillock.so
    module_arguments: authfail unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
      }}
    state: after
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3

- name: Add unlock_time argument to auth pam_faillock authfail
  pamd:
    name: '{{ item }}'
    type: auth
    control: '[default=die]'
    module_path: pam_faillock.so
    module_arguments: authfail unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
      }}
    state: args_present
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3

- name: Add account pam_faillock before pam_unix.so
  pamd:
    name: '{{ item }}'
    type: account
    control: required
    module_path: pam_unix.so
    new_type: account
    new_control: required
    new_module_path: pam_faillock.so
    state: before
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_unlock_time
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80670-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.7
    - CJIS-5.5.3
OVAL test results details

check preauth maximum failed login attempts allowed in /etc/pam.d/system-auth  oval:ssg-test_accounts_passwords_pam_faillock_unlock_time_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_unlock_time_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth^\s*auth\s+(?:(?:required))\s+pam_faillock\.so\s+preauth.*unlock_time=([0-9]*).*$1

check authfail maximum failed login attempts allowed in /etc/pam.d/system-auth  oval:ssg-test_accounts_passwords_pam_faillock_authfail_unlock_time_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_authfail_unlock_time_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth^\s*auth\s+(?:(?:sufficient)|(?:\[default=die\]))\s+pam_faillock\.so\s+authfail.*unlock_time=([0-9]*).*$1

check authfail maximum failed login attempts allowed in /etc/pam.d/password-auth  oval:ssg-test_accounts_passwords_pam_faillock_unlock_time_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_unlock_time_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/password-auth^\s*auth\s+(?:(?:sufficient)|(?:\[default=die\]))\s+pam_faillock\.so\s+authfail.*unlock_time=([0-9]*).*$1

check preauth maximum failed login attempts allowed in /etc/pam.d/password-auth  oval:ssg-test_accounts_passwords_pam_faillock_preauth_unlock_time_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_preauth_unlock_time_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/password-auth^\s*auth\s+(?:(?:required))\s+pam_faillock\.so\s+preauth.*unlock_time=([0-9]*).*$1
Set Deny For Failed Password Attemptsxccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_deny mediumCCE-80667-9

Set Deny For Failed Password Attempts

Rule IDxccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_deny
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_passwords_pam_faillock_deny:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80667-9

References:  5.3.2, 1, 12, 15, 16, 5.5.3, DSS05.04, DSS05.10, DSS06.10, 3.1.8, CCI-000044, CCI-002238, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(a), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.6, SRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005, SRG-OS-000021-VMM-000050

Description

To configure the system to lock out accounts after a number of incorrect login attempts using pam_faillock.so, modify the content of both /etc/pam.d/system-auth and /etc/pam.d/password-auth as follows:

  • add the following line immediately before the pam_unix.so statement in the AUTH section:
    auth required pam_faillock.so preauth silent deny=6 unlock_time=1800 fail_interval=900
  • add the following line immediately after the pam_unix.so statement in the AUTH section:
    auth [default=die] pam_faillock.so authfail deny=6 unlock_time=1800 fail_interval=900
  • add the following line immediately before the pam_unix.so statement in the ACCOUNT section:
    account required pam_faillock.so

Rationale

Locking out user accounts after a number of incorrect attempts prevents direct password guessing attacks.



# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_accounts_passwords_pam_faillock_deny="6"

AUTH_FILES=("/etc/pam.d/system-auth" "/etc/pam.d/password-auth")

for pam_file in "${AUTH_FILES[@]}"
do
    # is auth required pam_faillock.so preauth present?
    if grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*$' "$pam_file" ; then
        # is the option set?
        if grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*'"deny"'=([0-9]*).*$' "$pam_file" ; then
            # just change the value of option to a correct value
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock.so.*preauth.*silent.*\)\('"deny"' *= *\).*/\1\2'"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
        # the option is not set.
        else
            # append the option
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock.so.*preauth.*silent.*/ s/$/ '"deny"'='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
        fi
    # auth required pam_faillock.so preauth is not present, insert the whole line
    else
        sed -i --follow-symlinks '/^auth.*sufficient.*pam_unix.so.*/i auth        required      pam_faillock.so preauth silent '"deny"'='"$var_accounts_passwords_pam_faillock_deny" "$pam_file"
    fi
    # is auth default pam_faillock.so authfail present?
    if grep -qE '^\s*auth\s+(\[default=die\])\s+pam_faillock\.so\s+authfail.*$' "$pam_file" ; then
        # is the option set?
        if grep -qE '^\s*auth\s+(\[default=die\])\s+pam_faillock\.so\s+authfail.*'"deny"'=([0-9]*).*$' "$pam_file" ; then
            # just change the value of option to a correct value
            sed -i --follow-symlinks 's/\(^auth.*[default=die].*pam_faillock.so.*authfail.*\)\('"deny"' *= *\).*/\1\2'"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
        # the option is not set.
        else
            # append the option
            sed -i --follow-symlinks '/^auth.*[default=die].*pam_faillock.so.*authfail.*/ s/$/ '"deny"'='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
        fi
    # auth default pam_faillock.so authfail is not present, insert the whole line
    else
        sed -i --follow-symlinks '/^auth.*sufficient.*pam_unix.so.*/a auth        [default=die] pam_faillock.so authfail '"deny"'='"$var_accounts_passwords_pam_faillock_deny" "$pam_file"
    fi
    if ! grep -qE '^\s*account\s+required\s+pam_faillock\.so.*$' "$pam_file" ; then
        sed -E -i --follow-symlinks '/^\s*account\s*required\s*pam_unix.so/i account     required      pam_faillock.so' "$pam_file"
    fi
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3
- name: XCCDF Value var_accounts_passwords_pam_faillock_deny # promote to variable
  set_fact:
    var_accounts_passwords_pam_faillock_deny: !!str 6
  tags:
    - always

- name: Add auth pam_faillock preauth deny before pam_unix.so
  pamd:
    name: '{{ item }}'
    type: auth
    control: sufficient
    module_path: pam_unix.so
    new_type: auth
    new_control: required
    new_module_path: pam_faillock.so
    module_arguments: preauth silent deny={{ var_accounts_passwords_pam_faillock_deny
      }}
    state: before
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3

- name: Add deny argument to auth pam_faillock preauth
  pamd:
    name: '{{ item }}'
    type: auth
    control: required
    module_path: pam_faillock.so
    module_arguments: preauth silent deny={{ var_accounts_passwords_pam_faillock_deny
      }}
    state: args_present
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3

- name: Add auth pam_faillock authfail deny after pam_unix.so
  pamd:
    name: '{{ item }}'
    type: auth
    control: sufficient
    module_path: pam_unix.so
    new_type: auth
    new_control: '[default=die]'
    new_module_path: pam_faillock.so
    module_arguments: authfail deny={{ var_accounts_passwords_pam_faillock_deny }}
    state: after
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3

- name: Add deny argument to auth pam_faillock authfail
  pamd:
    name: '{{ item }}'
    type: auth
    new_type: auth
    control: '[default=die]'
    module_path: pam_faillock.so
    module_arguments: authfail deny={{ var_accounts_passwords_pam_faillock_deny }}
    state: args_present
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3

- name: Add account pam_faillock before pam_unix.so
  pamd:
    name: '{{ item }}'
    type: account
    control: required
    module_path: pam_unix.so
    new_type: account
    new_control: required
    new_module_path: pam_faillock.so
    state: before
  loop:
    - system-auth
    - password-auth
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_passwords_pam_faillock_deny
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80667-9
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-7(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-8.1.6
    - CJIS-5.5.3
OVAL test results details

Check pam_faillock.so preauth silent present, with correct deny value, and is followed by pam_unix.  oval:ssg-test_accounts_passwords_pam_faillock_preauth_silent_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_preauth_silent_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth[\n][\s]*auth[\s]+required[\s]+pam_faillock\.so[\s]+preauth[\s]+[^\n]*silent[\s]+[^\n]*deny=([0-9]+)[\s]*(?s).*[\n][\s]*auth[^\n]+pam_unix\.so[^\n]*[\n]1

Check if pam_faillock.so is called in account phase before pam_unix  oval:ssg-test_accounts_passwords_pam_faillock_account_phase_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_account_phase_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth[\n][\s]*account[\s]+required[\s]+pam_faillock\.so[^\n]*[\n][\s]*account[\s]+required[\s]+pam_unix\.so[^\n]*[\n]1

Check pam_faillock.so preauth silent present in /etc/pam.d/password-auth, has correct deny value, and is followed by pam_unix  oval:ssg-test_accounts_passwords_pam_faillock_preauth_silent_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_preauth_silent_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/password-auth[\n][\s]*auth[\s]+required[\s]+pam_faillock\.so[\s]+preauth[\s]+[^\n]*silent[\s]+[^\n]*deny=([0-9]+)[\s]*(?s).*[\n][\s]*auth[^\n]+pam_unix\.so[^\n]*[\n]1

Check if pam_faillock_so is called in account phase before pam_unix.  oval:ssg-test_accounts_passwords_pam_faillock_account_phase_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_account_phase_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/password-auth[\n][\s]*account[\s]+required[\s]+pam_faillock\.so[^\n]*[\n][\s]*account[\s]+required[\s]+pam_unix\.so[^\n]*[\n]1

Checks if pam_faillock authfail is hit even if pam_unix skips lines by defaulting, and also authfail deny value  oval:ssg-test_accounts_passwords_pam_faillock_numeric_default_check_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_when_lines_skipped_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
6Referenced variable has no values (oval:ssg-var_accounts_passwords_pam_faillock_preauth_default_lin/etc/pam.d/system-auth1

Check control values of pam_unix, that it is followed by pam_faillock.so authfail and deny value of pam_faillock.so authfail  oval:ssg-test_accounts_passwords_pam_faillock_authfail_deny_system-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_authfail_deny_system-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth[\n][\s]*auth[\s]+(?:(?:sufficient)|(?:\[[^\]]*default=ignore[^\]]*\]))[^\n]+pam_unix\.so(?:.*[\n])*auth[\s]+\[default=die\][\s]+pam_faillock\.so[\s]+authfail[^\n]+deny=([0-9]+)1

Checks if pam_faillock authfail is hit even if pam_unix skips lines by defaulting, and also authfail deny value  oval:ssg-test_accounts_passwords_pam_faillock_numeric_default_check_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_when_lines_skipped_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
6Referenced variable has no values (oval:ssg-var_accounts_passwords_pam_faillock_preauth_default_lin/etc/pam.d/password-auth1

Check pam_faillock authfail is present after pam_unix, check pam_unix has proper control values, and authfail deny value is correct.  oval:ssg-test_accounts_passwords_pam_faillock_authfail_deny_password-auth:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_passwords_pam_faillock_authfail_deny_password-auth:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/password-auth[\n][\s]*auth[\s]+(?:(?:sufficient)|(?:\[[^\]]*default=ignore[[^\]]*\]))[\s]+pam_unix\.so(?:.*[\n])*[^\n]*auth[\s]+\[default=die\][\s]+pam_faillock\.so[\s]+authfail[\s]+[^\n]*deny=([0-9]+)1
Limit Password Reusexccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember mediumCCE-80666-1

Limit Password Reuse

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_pam_unix_remember:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80666-1

References:  5.3.3, 1, 12, 15, 16, 5, 5.6.2.1.1, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.5.8, CCI-000200, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(f), IA-5(1)(e), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.5, SRG-OS-000077-GPOS-00045, SRG-OS-000077-VMM-000440

Description

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=4 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=4
  • for the pam_pwhistory.so case:
    password requisite pam_pwhistory.so ...existing_options... remember=4
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.



# Remediation is applicable only in certain platforms
if rpm --quiet -q pam; then


var_password_pam_unix_remember="4"

AUTH_FILES[0]="/etc/pam.d/system-auth"
AUTH_FILES[1]="/etc/pam.d/password-auth"

for pamFile in "${AUTH_FILES[@]}"
do
	if grep -q "remember=" $pamFile; then
		sed -i --follow-symlinks "s/\(^password.*sufficient.*pam_unix.so.*\)\(\(remember *= *\)[^ $]*\)/\1remember=$var_password_pam_unix_remember/" $pamFile
	else
		sed -i --follow-symlinks "/^password[[:space:]]\+sufficient[[:space:]]\+pam_unix.so/ s/$/ remember=$var_password_pam_unix_remember/" $pamFile
	fi
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:medium
Strategy:configure
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_unix_remember
    - medium_severity
    - configure_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80666-1
    - NIST-800-53-IA-5(f)
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-171-3.5.8
    - PCI-DSS-Req-8.2.5
    - CJIS-5.6.2.1.1
- name: XCCDF Value var_password_pam_unix_remember # promote to variable
  set_fact:
    var_password_pam_unix_remember: !!str 4
  tags:
    - always

- name: Do not allow users to reuse recent passwords - system-auth (change)
  replace:
    dest: /etc/pam.d/system-auth
    follow: true
    regexp: ^(password\s+sufficient\s+pam_unix\.so\s.*remember\s*=\s*)(\S+)(.*)$
    replace: \g<1>{{ var_password_pam_unix_remember }}\g<3>
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_unix_remember
    - medium_severity
    - configure_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80666-1
    - NIST-800-53-IA-5(f)
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-171-3.5.8
    - PCI-DSS-Req-8.2.5
    - CJIS-5.6.2.1.1

- name: Do not allow users to reuse recent passwords - system-auth (add)
  replace:
    dest: /etc/pam.d/system-auth
    follow: true
    regexp: ^password\s+sufficient\s+pam_unix\.so\s(?!.*remember\s*=\s*).*$
    replace: \g<0> remember={{ var_password_pam_unix_remember }}
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_unix_remember
    - medium_severity
    - configure_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80666-1
    - NIST-800-53-IA-5(f)
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-171-3.5.8
    - PCI-DSS-Req-8.2.5
    - CJIS-5.6.2.1.1
OVAL test results details

Test if remember attribute of pam_unix.so is set correctly in /etc/pam.d/system-auth  oval:ssg-test_accounts_password_pam_unix_remember:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_password_pam_unix_remember:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth^\s*password\s+(?:(?:sufficient)|(?:required))\s+pam_unix\.so.*remember=([0-9]*).*$1

Test if remember attribute of pam_pwhistory.so is set correctly in /etc/pam.d/system-auth  oval:ssg-test_accounts_password_pam_pwhistory_remember:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_accounts_password_pam_pwhistory_remember:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/pam.d/system-auth^\s*password\s+(?:(?:requisite)|(?:required))\s+pam_pwhistory\.so.*remember=([0-9]*).*$1
Install the opensc Package For Multifactor Authenticationxccdf_org.ssgproject.content_rule_package_opensc_installed mediumCCE-80846-9

Install the opensc Package For Multifactor Authentication

Rule IDxccdf_org.ssgproject.content_rule_package_opensc_installed
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-package_opensc_installed:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80846-9

References:  CCI-001954, CM-6(a), SRG-OS-000375-GPOS-00160, SRG-OS-000376-VMM-001520

Description

The opensc package can be installed with the following command:

$ sudo yum install opensc

Rationale

Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.



Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "opensc" ; then
    yum install -y "opensc"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:enable
- name: Ensure opensc is installed
  package:
    name: opensc
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - package_opensc_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80846-9
    - NIST-800-53-CM-6(a)


Complexity:low
Disruption:low
Strategy:enable
include install_opensc

class install_opensc {
  package { 'opensc':
    ensure => 'installed',
  }
}


Complexity:low
Disruption:low
Strategy:enable

package --add=opensc
OVAL test results details

package opensc is installed  oval:ssg-test_package_opensc_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_opensc_installed:obj:1 of type rpminfo_object
Name
opensc
Install the pcsc-lite packagexccdf_org.ssgproject.content_rule_package_pcsc-lite_installed mediumCCE-80993-9

Install the pcsc-lite package

Rule IDxccdf_org.ssgproject.content_rule_package_pcsc-lite_installed
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-package_pcsc-lite_installed:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80993-9

References:  CCI-001954, CM-6(a), SRG-OS-000375-GPOS-00160, SRG-OS-000377-VMM-001530

Description

The pcsc-lite package can be installed with the following command:

$ sudo yum install pcsc-lite

Rationale

The pcsc-lite package must be installed if it is to be available for multifactor authentication using smartcards.



Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "pcsc-lite" ; then
    yum install -y "pcsc-lite"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:enable
- name: Ensure pcsc-lite is installed
  package:
    name: pcsc-lite
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - package_pcsc-lite_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80993-9
    - NIST-800-53-CM-6(a)


Complexity:low
Disruption:low
Strategy:enable
include install_pcsc-lite

class install_pcsc-lite {
  package { 'pcsc-lite':
    ensure => 'installed',
  }
}


Complexity:low
Disruption:low
Strategy:enable

package --add=pcsc-lite
OVAL test results details

package pcsc-lite is installed  oval:ssg-test_package_pcsc-lite_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_pcsc-lite_installed:obj:1 of type rpminfo_object
Name
pcsc-lite
Enable the pcscd Servicexccdf_org.ssgproject.content_rule_service_pcscd_enabled mediumCCE-80881-6

Enable the pcscd Service

Rule IDxccdf_org.ssgproject.content_rule_service_pcscd_enabled
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-service_pcscd_enabled:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80881-6

References:  CCI-001954, IA-2(1), IA-2(2), IA-2(3), IA-2(4), IA-2(6), IA-2(7), IA-2(11), CM-6(a), SRG-OS-000375-GPOS-00160, SRG-OS-000377-VMM-001530

Description

The pcscd service can be enabled with the following command:

$ sudo systemctl enable pcscd.service

Rationale

Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.



Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" start 'pcscd.service'
"$SYSTEMCTL_EXEC" enable 'pcscd.service'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:enable
- name: Enable service pcscd
  block:

    - name: Gather the package facts
      package_facts:
        manager: auto

    - name: Enable service pcscd
      service:
        name: pcscd
        enabled: 'yes'
        state: started
      when:
        - '"pcsc-lite" in ansible_facts.packages'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - service_pcscd_enabled
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80881-6
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-CM-6(a)


Complexity:low
Disruption:low
Strategy:enable
include enable_pcscd

class enable_pcscd {
  service {'pcscd':
    enable => true,
    ensure => 'running',
  }
}
OVAL test results details

package pcsc-lite is installed  oval:ssg-test_service_pcscd_package_pcsc-lite_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_service_pcscd_package_pcsc-lite_installed:obj:1 of type rpminfo_object
Name
pcsc-lite

Test that the pcscd service is running  oval:ssg-test_service_running_pcscd:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_service_running_pcscd:obj:1 of type systemdunitproperty_object
UnitProperty
^pcscd\.(socket|service)$ActiveState

systemd test  oval:ssg-test_multi_user_wants_pcscd:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_pcscd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service
Configure opensc Smart Card Driversxccdf_org.ssgproject.content_rule_configure_opensc_card_drivers mediumCCE-80766-9

Configure opensc Smart Card Drivers

Rule IDxccdf_org.ssgproject.content_rule_configure_opensc_card_drivers
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_opensc_card_drivers:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80766-9

References:  1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000765, CCI-000766, CCI-000767, CCI-000768, CCI-000771, CCI-000772, CCI-000884, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-2(1), IA-2(2), IA-2(3), IA-2(4), IA-2(6), IA-2(7), IA-2(11), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.3, SRG-OS-000104-GPOS-00051, SRG-OS-000106-GPOS-00053, SRG-OS-000107-GPOS-00054, SRG-OS-000109-GPOS-00056, SRG-OS-000108-GPOS-00055, SRG-OS-000108-GPOS-00057, SRG-OS-000108-GPOS-00058, SRG-OS-000376-VMM-001520

Description

The OpenSC smart card tool can auto-detect smart card drivers; however, setting the smart card drivers in use by your organization helps to prevent users from using unauthorized smart cards. The default smart card driver for this profile is cac. To configure the OpenSC driver, edit the /etc/opensc-ARCH.conf (where ARCH is the architecture of your operating system) file. Look for a line similar to:

# card_drivers = old, internal;
and change it to:
card_drivers = cac;

Rationale

Smart card login provides two-factor authentication stronger than that provided by a username and password combination. Smart cards leverage PKI (public key infrastructure) in order to provide and verify credentials. Configuring the smart card driver in use by your organization helps to prevent users from using unauthorized smart cards.



Complexity:low
Disruption:low
Strategy:configure
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_smartcard_drivers="cac"

OPENSC_TOOL="/usr/bin/opensc-tool"

if [ -f "${OPENSC_TOOL}" ]; then
    ${OPENSC_TOOL} -S app:default:card_drivers:$var_smartcard_drivers
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: XCCDF Value var_smartcard_drivers # promote to variable
  set_fact:
    var_smartcard_drivers: !!str cac
  tags:
    - always

- name: Check existence of opensc conf
  stat:
    path: /etc/opensc-{{ ansible_architecture }}.conf
  register: opensc_conf_cd
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - configure_opensc_card_drivers
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80766-9
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.3

- name: Configure opensc Smart Card Drivers
  lineinfile:
    path: /etc/opensc-{{ ansible_architecture }}.conf
    line: '        card_drivers = {{ var_smartcard_drivers }}'
    regexp: (^\s+#|^)\s+card_drivers\s+=\s+.*
    state: present
  when:
    - opensc_conf_cd.stat.exists
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - configure_opensc_card_drivers
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80766-9
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.3
OVAL test results details

Check that card_drivers is configured for opensc  oval:ssg-test_configure_opensc_card_drivers:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_configure_opensc_card_drivers:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/opensc.*.conf$^[\s]+card_drivers[\s]+=[\s]+(\S+);$1
Force opensc To Use Defined Smart Card Driverxccdf_org.ssgproject.content_rule_force_opensc_card_drivers mediumCCE-80821-2

Force opensc To Use Defined Smart Card Driver

Rule IDxccdf_org.ssgproject.content_rule_force_opensc_card_drivers
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-force_opensc_card_drivers:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80821-2

References:  1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000765, CCI-000766, CCI-000767, CCI-000768, CCI-000771, CCI-000772, CCI-000884, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-2(1), IA-2(2), IA-2(3), IA-2(4), IA-2(6), IA-2(7), IA-2(11), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.3, SRG-OS-000104-GPOS-00051, SRG-OS-000106-GPOS-00053, SRG-OS-000107-GPOS-00054, SRG-OS-000109-GPOS-00056, SRG-OS-000108-GPOS-00055, SRG-OS-000108-GPOS-00057, SRG-OS-000108-GPOS-00058, SRG-OS-000376-VMM-001520

Description

The OpenSC smart card tool can auto-detect smart card drivers; however by forcing the smart card driver in use by your organization, opensc will no longer autodetect or use other drivers unless specified. This helps to prevent users from using unauthorized smart cards. The default smart card driver for this profile is cac. To force the OpenSC driver, edit the /etc/opensc-ARCH.conf (where ARCH is the architecture of your operating system) file. Look for a line similar to:

# force_card_driver = customcos;
and change it to:
force_card_driver = cac;

Rationale

Smart card login provides two-factor authentication stronger than that provided by a username and password combination. Smart cards leverage PKI (public key infrastructure) in order to provide and verify credentials. Forcing the smart card driver in use by your organization helps to prevent users from using unauthorized smart cards.



Complexity:low
Disruption:low
Strategy:configure
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_smartcard_drivers="cac"

OPENSC_TOOL="/usr/bin/opensc-tool"

if [ -f "${OPENSC_TOOL}" ]; then
    ${OPENSC_TOOL} -S app:default:force_card_driver:$var_smartcard_drivers
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: XCCDF Value var_smartcard_drivers # promote to variable
  set_fact:
    var_smartcard_drivers: !!str cac
  tags:
    - always

- name: Check existence of opensc conf
  stat:
    path: /etc/opensc-{{ ansible_architecture }}.conf
  register: opensc_conf_fcd
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - force_opensc_card_drivers
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80821-2
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.3

- name: Force opensc To Use Defined Smart Card Driver
  lineinfile:
    path: /etc/opensc-{{ ansible_architecture }}.conf
    line: '        force_card_driver = {{ var_smartcard_drivers }}'
    regexp: (^\s+#|^)\s+force_card_driver\s+=\s+.*
    state: present
  when:
    - opensc_conf_fcd.stat.exists
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - force_opensc_card_drivers
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80821-2
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.3
OVAL test results details

Check that force_card_driver is configured for opensc  oval:ssg-test_force_opensc_card_drivers:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_force_opensc_card_drivers:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/opensc.*.conf$^[\s]+force_card_driver[\s]+=[\s]+(\S+);$1
Verify All Account Password Hashes are Shadowedxccdf_org.ssgproject.content_rule_accounts_password_all_shadowed mediumCCE-80651-3

Verify All Account Password Hashes are Shadowed

Rule IDxccdf_org.ssgproject.content_rule_accounts_password_all_shadowed
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-accounts_password_all_shadowed:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80651-3

References:  1, 12, 15, 16, 5, 5.5.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.5.10, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(h), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1

Description

If any password hashes are stored in /etc/passwd (in the second field, instead of an x or *), the cause of this misconfiguration should be investigated. The account should have its password reset and the hash should be properly stored, or the account should be deleted entirely.

Rationale

The hashes for all user account passwords should be stored in the file /etc/shadow and never in /etc/passwd, which is readable by all users.

OVAL test results details

password hashes are shadowed  oval:ssg-test_accounts_password_all_shadowed:tst:1  true

Following items have been found on the system:
UsernamePasswordUser idGroup idGcosHome dirLogin shellLast login
rootx00root/root/bin/bash1616352455
polkitdx998996User for polkitd//sbin/nologin0
unboundx997994Unbound DNS resolver/etc/unbound/sbin/nologin0
sssdx996993User for sssd//sbin/nologin0
chronyx995992/var/lib/chrony/sbin/nologin0
sshdx7474Privilege-separated SSH/var/empty/sshd/sbin/nologin0
cockpit-wsinstancex992988User for cockpit-ws instances/nonexisting/sbin/nologin0
setroubleshootx991987/var/lib/setroubleshoot/sbin/nologin0
rngdx994991Random Number Generator Daemon/var/lib/rngd/sbin/nologin0
userx10001000user/home/user/bin/bash1611520538
johnx10021002/home/john/bin/bash0
ellenx10031003/home/ellen/bin/bash0
soniax10041004/home/sonia/bin/bash1611809012
matildex10051005/home/matilde/bin/bash1611808989
user01x10011001/home/user01/bin/bash0
apachex4848Apache/usr/share/httpd/sbin/nologin0
cockpit-wsx993989User for cockpit web service/nonexisting/sbin/nologin0
dbusx8181System message bus//sbin/nologin0
systemd-resolvex193193systemd Resolver//sbin/nologin0
tssx5959Account used by the trousers package to sandbox the tcsd daemon/dev/null/sbin/nologin0
operatorx110operator/root/sbin/nologin0
ftpx1450FTP User/var/ftp/sbin/nologin0
nobodyx6553465534Kernel Overflow User//sbin/nologin-1
systemd-coredumpx999997systemd Core Dumper//sbin/nologin0
haltx70halt/sbin/sbin/halt0
mailx812mail/var/spool/mail/sbin/nologin0
shutdownx60shutdown/sbin/sbin/shutdown0
syncx50sync/sbin/bin/sync0
admx34adm/var/adm/sbin/nologin0
lpx47lp/var/spool/lpd/sbin/nologin0
daemonx22daemon/sbin/sbin/nologin0
binx11bin/bin/sbin/nologin0
gamesx12100games/usr/games/sbin/nologin0
All GIDs referenced in /etc/passwd must be defined in /etc/groupxccdf_org.ssgproject.content_rule_gid_passwd_group_same lowCCE-80822-0

All GIDs referenced in /etc/passwd must be defined in /etc/group

Rule IDxccdf_org.ssgproject.content_rule_gid_passwd_group_same
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-gid_passwd_group_same:def:1
Time2021-03-21T20:15:13+01:00
Severitylow
Identifiers and References

Identifiers:  CCE-80822-0

References:  1, 12, 15, 16, 5, 5.5.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000764, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-2, CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.5.a, SRG-OS-000104-GPOS-00051

Description

Add a group to the system for each GID referenced without a corresponding group.

Rationale

If a user is assigned the Group Identifier (GID) of a group not existing on the system, and a group with the Gruop Identifier (GID) is subsequently created, the user may have unintended rights to any files associated with the group.

OVAL test results details

Verify all GIDs referenced in /etc/passwd are defined in /etc/group  oval:ssg-test_gid_passwd_group_same:tst:1  true

Following items have been found on the system:
PathContent
/etc/passwdmail:x:8:12:
/etc/passwdsync:x:5:0:
/etc/passwdtss:x:59:59:
/etc/passwdpolkitd:x:998:996:
/etc/passwdsshd:x:74:74:
/etc/passwdrngd:x:994:991:
/etc/passwduser:x:1000:1000:
/etc/passwdjohn:x:1002:1002:
/etc/passwdellen:x:1003:1003:
/etc/passwdshutdown:x:6:0:
/etc/passwdhalt:x:7:0:
/etc/passwdbin:x:1:1:
/etc/passwddaemon:x:2:2:
/etc/passwdsonia:x:1004:1004:
/etc/passwdmatilde:x:1005:1005:
/etc/passwduser01:x:1001:1001:
/etc/passwdapache:x:48:48:
/etc/passwdcockpit-ws:x:993:989:
/etc/passwdcockpit-wsinstance:x:992:988:
/etc/passwdsetroubleshoot:x:991:987:
/etc/passwdlp:x:4:7:
/etc/passwdsystemd-resolve:x:193:193:
/etc/passwdunbound:x:997:994:
/etc/passwdsssd:x:996:993:
/etc/passwdchrony:x:995:992:
/etc/passwdadm:x:3:4:
/etc/passwddbus:x:81:81:
/etc/passwdftp:x:14:50:
/etc/passwdnobody:x:65534:65534:
/etc/passwdsystemd-coredump:x:999:997:
/etc/passwdgames:x:12:100:
/etc/passwdoperator:x:11:0:
/etc/passwdroot:x:0:0:
Prevent Login to Accounts With Empty Passwordxccdf_org.ssgproject.content_rule_no_empty_passwords highCCE-80841-0

Prevent Login to Accounts With Empty Password

Rule IDxccdf_org.ssgproject.content_rule_no_empty_passwords
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-no_empty_passwords:def:1
Time2021-03-21T20:15:13+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80841-0

References:  1, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2, APO01.06, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.10, 3.1.1, 3.1.5, CCI-000366, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.18.1.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, IA-5(1)(a), IA-5(c), CM-6(a), PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5, FIA_AFL.1, Req-8.2.3, SRG-OS-000480-GPOS-00227

Description

If an account is configured for password authentication but does not have an assigned password, it may be possible to log into the account without authentication. Remove any instances of the nullok option in /etc/pam.d/system-auth to prevent logins with empty passwords.

Rationale

If an account has an empty password, anyone could log in and run commands with the privileges of that account. Accounts with empty passwords should never be used in operational environments.



sed --follow-symlinks -i 's/\<nullok\>//g' /etc/pam.d/system-auth
sed --follow-symlinks -i 's/\<nullok\>//g' /etc/pam.d/password-auth


Complexity:low
Disruption:medium
Strategy:configure
- name: Prevent Log In to Accounts With Empty Password - system-auth
  replace:
    dest: /etc/pam.d/system-auth
    follow: true
    regexp: nullok
  tags:
    - no_empty_passwords
    - high_severity
    - configure_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80841-0
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - PCI-DSS-Req-8.2.3
    - CJIS-5.5.2

- name: Prevent Log In to Accounts With Empty Password - password-auth
  replace:
    dest: /etc/pam.d/password-auth
    follow: true
    regexp: nullok
  tags:
    - no_empty_passwords
    - high_severity
    - configure_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80841-0
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - PCI-DSS-Req-8.2.3
    - CJIS-5.5.2


apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
spec:
  config:
    ignition:
      version: 2.2.0
    storage:
      files:
      - contents:
          source: data:,%23%20Generated%20by%20authselect%20on%20Sat%20Oct%2027%2014%3A59%3A36%202018%0A%23%20Do%20not%20modify%20this%20file%20manually.%0A%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_env.so%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_faildelay.so%20delay%3D2000000%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_fprintd.so%0Aauth%20%20%20%20%20%20%20%20%5Bdefault%3D1%20ignore%3Dignore%20success%3Dok%5D%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3E%3D%201000%20quiet%0Aauth%20%20%20%20%20%20%20%20%5Bdefault%3D1%20ignore%3Dignore%20success%3Dok%5D%20%20%20%20%20%20%20%20%20pam_localuser.so%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%20try_first_pass%0Aauth%20%20%20%20%20%20%20%20requisite%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3E%3D%201000%20quiet_success%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%20forward_pass%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_deny.so%0A%0Aaccount%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%0Aaccount%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_localuser.so%0Aaccount%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3C%201000%20quiet%0Aaccount%20%20%20%20%20%5Bdefault%3Dbad%20success%3Dok%20user_unknown%3Dignore%5D%20pam_sss.so%0Aaccount%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_permit.so%0A%0Apassword%20%20%20%20requisite%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_pwquality.so%20try_first_pass%20local_users_only%0Apassword%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%20sha512%20shadow%20try_first_pass%20use_authtok%0Apassword%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%20use_authtok%0Apassword%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_deny.so%0A%0Asession%20%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_keyinit.so%20revoke%0Asession%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_limits.so%0A-session%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_systemd.so%0Asession%20%20%20%20%20%5Bsuccess%3D1%20default%3Dignore%5D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20service%20in%20crond%20quiet%20use_uid%0Asession%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%0Asession%20%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%0A
        filesystem: root
        mode: 0644
        path: /etc/pam.d/password-auth
      - contents:
          source: data:,%23%20Generated%20by%20authselect%20on%20Sat%20Oct%2027%2014%3A59%3A36%202018%0A%23%20Do%20not%20modify%20this%20file%20manually.%0A%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_env.so%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_faildelay.so%20delay%3D2000000%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_fprintd.so%0Aauth%20%20%20%20%20%20%20%20%5Bdefault%3D1%20ignore%3Dignore%20success%3Dok%5D%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3E%3D%201000%20quiet%0Aauth%20%20%20%20%20%20%20%20%5Bdefault%3D1%20ignore%3Dignore%20success%3Dok%5D%20%20%20%20%20%20%20%20%20pam_localuser.so%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%20try_first_pass%0Aauth%20%20%20%20%20%20%20%20requisite%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3E%3D%201000%20quiet_success%0Aauth%20%20%20%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%20forward_pass%0Aauth%20%20%20%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_deny.so%0A%0Aaccount%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%0Aaccount%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_localuser.so%0Aaccount%20%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20uid%20%3C%201000%20quiet%0Aaccount%20%20%20%20%20%5Bdefault%3Dbad%20success%3Dok%20user_unknown%3Dignore%5D%20pam_sss.so%0Aaccount%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_permit.so%0A%0Apassword%20%20%20%20requisite%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_pwquality.so%20try_first_pass%20local_users_only%0Apassword%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%20sha512%20shadow%20try_first_pass%20use_authtok%0Apassword%20%20%20%20sufficient%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%20use_authtok%0Apassword%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_deny.so%0A%0Asession%20%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_keyinit.so%20revoke%0Asession%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_limits.so%0A-session%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_systemd.so%0Asession%20%20%20%20%20%5Bsuccess%3D1%20default%3Dignore%5D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_succeed_if.so%20service%20in%20crond%20quiet%20use_uid%0Asession%20%20%20%20%20required%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_unix.so%0Asession%20%20%20%20%20optional%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pam_sss.so%0A
        filesystem: root
        mode: 0644
        path: /etc/pam.d/system-auth
OVAL test results details

make sure nullok is not used in /etc/pam.d/system-auth  oval:ssg-test_no_empty_passwords:tst:1  false

Following items have been found on the system:
PathContent
/etc/pam.d/system-authauth required pam_env.so auth sufficient pam_unix.so try_first_pass nullok auth required pam_deny.so account required pam_unix.so password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow
Record Unsuccessful Access Attempts to Files - openxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_open mediumCCE-80753-7

Record Unsuccessful Access Attempts to Files - open

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_open
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_open:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80753-7

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit open tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_open
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/access.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/access.rules
  when:
    - find_open.matched is defined and find_open.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_open.files | map(attribute=''path'') | list | first }}'
  when:
    - find_open.matched is defined and find_open.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open rule in audit.rules when on x86_64
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S open -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S open -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80753-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_open_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_open_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_open_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_open_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_open_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_open_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_open_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_open_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_open_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_open_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_open_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_open_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_open_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_open_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_open_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_open_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open[\s]+|([\s]+|[,])open([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1
Record Unsuccessful Access Attempts to Files - truncatexccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_truncate mediumCCE-80756-0

Record Unsuccessful Access Attempts to Files - truncate

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_truncate
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_truncate:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80756-0

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit truncate tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_truncate
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/access.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/access.rules
  when:
    - find_truncate.matched is defined and find_truncate.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_truncate.files | map(attribute=''path'') | list | first }}'
  when:
    - find_truncate.matched is defined and find_truncate.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the truncate rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the truncate rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the truncate rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the truncate rule in audit.rules when on x86_64
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S truncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S truncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_truncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80756-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_truncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_truncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_truncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_truncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_truncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_truncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_truncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_truncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_truncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_truncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_truncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_truncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_truncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_truncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_truncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_truncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+truncate[\s]+|([\s]+|[,])truncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1
Record Unsuccessful Access Attempts to Files - creatxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_creat mediumCCE-80751-1

Record Unsuccessful Access Attempts to Files - creat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_creat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_creat:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80751-1

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Add unsuccessful file operations audit rules
  blockinfile:
    path: /etc/audit/rules.d/30-ospp-v42-remediation.rules
    create: true
    block: |-
      ## This content is a section of an Audit config snapshot recommended for Red Hat Enterprise Linux 8 systems that target OSPP compliance.
      ## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

      ## The purpose of these rules is to meet the requirements for Operating
      ## System Protection Profile (OSPP)v4.2. These rules depends on having
      ## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

      ## Unsuccessful file creation (open with O_CREAT)
      -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
      -a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

      ## Unsuccessful file modifications (open for write or truncate)
      -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
      -a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

      ## Unsuccessful file access (any other opens) This has to go last.
      -a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
      -a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
      -a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
      -a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_creat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80751-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_creat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_creat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_creat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_creat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_creat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_creat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_creat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_creat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_creat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_creat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_creat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_creat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_creat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_creat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_creat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_creat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+creat[\s]+|([\s]+|[,])creat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
/etc/audit/audit.rules1
Record Unsuccessful Access Attempts to Files - open_by_handle_atxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_open_by_handle_at mediumCCE-80755-2

Record Unsuccessful Access Attempts to Files - open_by_handle_at

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_open_by_handle_at
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_open_by_handle_at:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80755-2

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit open_by_handle_at tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_open_by_handle_at
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/access.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/access.rules
  when:
    - find_open_by_handle_at.matched is defined and find_open_by_handle_at.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_open_by_handle_at.files | map(attribute=''path'') | list | first
        }}'
  when:
    - find_open_by_handle_at.matched is defined and find_open_by_handle_at.matched
      > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open_by_handle_at rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EACCES -F auid>=1000
      -F auid!=unset -F key=access
    - -a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EPERM -F auid>=1000
      -F auid!=unset -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open_by_handle_at rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EACCES -F auid>=1000
      -F auid!=unset -F key=access
    - -a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EPERM -F auid>=1000
      -F auid!=unset -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open_by_handle_at rule in /etc/audit/audit.rules when
    on x86
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EACCES -F auid>=1000
      -F auid!=unset -F key=access
    - -a always,exit -F arch=b32 -S open_by_handle_at -F exit=-EPERM -F auid>=1000
      -F auid!=unset -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the open_by_handle_at rule in audit.rules when on x86_64
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EACCES -F auid>=1000
      -F auid!=unset -F key=access
    - -a always,exit -F arch=b64 -S open_by_handle_at -F exit=-EPERM -F auid>=1000
      -F auid!=unset -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80755-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_open_by_handle_at_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_open_by_handle_at_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_open_by_handle_at_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_open_by_handle_at_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_open_by_handle_at_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_open_by_handle_at_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_open_by_handle_at_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_open_by_handle_at_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_open_by_handle_at_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_open_by_handle_at_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_open_by_handle_at_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_open_by_handle_at_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_open_by_handle_at_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_open_by_handle_at_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_open_by_handle_at_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_open_by_handle_at_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+open_by_handle_at[\s]+|([\s]+|[,])open_by_handle_at([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1
Record Unsuccessful Access Attempts to Files - openatxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_openat mediumCCE-80754-5

Record Unsuccessful Access Attempts to Files - openat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_openat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_openat:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80754-5

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit openat tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_openat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/access.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/access.rules
  when:
    - find_openat.matched is defined and find_openat.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_openat.files | map(attribute=''path'') | list | first }}'
  when:
    - find_openat.matched is defined and find_openat.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the openat rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the openat rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the openat rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the openat rule in audit.rules when on x86_64
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_openat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80754-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_openat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_openat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_openat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_openat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_openat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_openat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_openat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_openat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_openat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_openat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_openat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_openat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_openat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_openat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_openat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_openat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+openat[\s]+|([\s]+|[,])openat([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1
Record Unsuccessful Access Attempts to Files - ftruncatexccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_ftruncate mediumCCE-80752-9

Record Unsuccessful Access Attempts to Files - ftruncate

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_unsuccessful_file_modification_ftruncate
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_unsuccessful_file_modification_ftruncate:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80752-9

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.4, Req-10.2.1, SRG-OS-000064-GPOS-00033, SRG-OS-000458-GPOS-00203, SRG-OS-000461-GPOS-00205, SRG-OS-000392-GPOS-00172, SRG-OS-000458-VMM-001810, SRG-OS-000461-VMM-001830

Description

At a minimum, the audit system should collect unauthorized file accesses for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d:

-a always,exit -F arch=b32 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S ftruncate -F exiu=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b32 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access
If the system is 64 bit then also add the following lines:
-a always,exit -F arch=b64 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=access
-a always,exit -F arch=b64 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=access

Rationale

Unsuccessful attempts to access files could be an indicator of malicious activity on a system. Auditing these events could serve as evidence of potential system compromise.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

#
function create_audit_remediation_unsuccessful_file_modification_detailed {
	mkdir -p "$(dirname "$1")"
	# The - option to mark a here document limit string (<<-EOF) suppresses leading tabs (but not spaces) in the output.
	cat <<-EOF > "$1"
		## This content is a section of an Audit config snapshot recommended for linux systems that target OSPP compliance.
		## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules

		## The purpose of these rules is to meet the requirements for Operating
		## System Protection Profile (OSPP)v4.2. These rules depends on having
		## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.

		## Unsuccessful file creation (open with O_CREAT)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create
		-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create

		## Unsuccessful file modifications (open for write or truncate)
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification
		-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification

		## Unsuccessful file access (any other opens) This has to go last.
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
		-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access
	EOF
}
create_audit_remediation_unsuccessful_file_modification_detailed /etc/audit/rules.d/30-ospp-v42-remediation.rules

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit ftruncate tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_ftruncate
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/access.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/access.rules
  when:
    - find_ftruncate.matched is defined and find_ftruncate.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_ftruncate.files | map(attribute=''path'') | list | first }}'
  when:
    - find_ftruncate.matched is defined and find_ftruncate.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the ftruncate rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the ftruncate rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: '{{ item }}'
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the ftruncate rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b32 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b32 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1

- name: Inserts/replaces the ftruncate rule in audit.rules when on x86_64
  lineinfile:
    line: '{{ item }}'
    state: present
    dest: /etc/audit/audit.rules
    create: true
  with_items:
    - -a always,exit -F arch=b64 -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset
      -F key=access
    - -a always,exit -F arch=b64 -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset
      -F key=access
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_unsuccessful_file_modification_ftruncate
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80752-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.4
    - PCI-DSS-Req-10.2.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_ftruncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_ftruncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_ftruncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_ftruncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_ftruncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_ftruncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit augenrules 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_ftruncate_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_ftruncate_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^/etc/audit/rules\.d/.*\.rules$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit file eacces  oval:ssg-test_32bit_arufm_eacces_ftruncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eacces_ftruncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 32-bit file eperm  oval:ssg-test_32bit_arufm_eperm_ftruncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_arufm_eperm_ftruncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit file eacces  oval:ssg-test_64bit_arufm_eacces_ftruncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eacces_ftruncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EACCES)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1

audit auditctl 64-bit file eperm  oval:ssg-test_64bit_arufm_eperm_ftruncate_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_arufm_eperm_ftruncate_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*
^[\s]*-a[\s]+always,exit[\s]+(?:-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+ftruncate[\s]+|([\s]+|[,])ftruncate([\s]+|[,])))(?:(?!-F[\s]+a\d&).)*(?:-F\s+exit=-EPERM)[\s]+(?:-F\s+auid>=1000[\s]+)(?:-F\s+auid!=(unset|4294967295)[\s]+)(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
/etc/audit/audit.rules1
Ensure auditd Collects Information on Kernel Module Loading and Unloading - finit_modulexccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_finit mediumCCE-80712-3

Ensure auditd Collects Information on Kernel Module Loading and Unloading - finit_module

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_finit
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_kernel_module_loading_finit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80712-3

References:  5.2.17, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000471-GPOS-00216, SRG-OS-000477-GPOS-00222, SRG-OS-000477-VMM-001970

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d to capture kernel module loading and unloading events, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S finit_module -F key=modules
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file in order to capture kernel module loading and unloading events, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S finit_module -F key=modules

Rationale

The addition/removal of kernel modules can be used to alter the behavior of the kernel and potentially introduce malicious code into kernel space. It is important to have an audit trail of modules that have been introduced into the kernel.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
# Note: 32-bit and 64-bit kernel syscall numbers not always line up =>
#       it's required on a 64-bit system to check also for the presence
#       of 32-bit's equivalent of the corresponding rule.
#       (See `man 7 audit.rules` for details )
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S finit_module \(-F key=\|-k \).*"
	GROUP="modules"
	FULL_RULE="-a always,exit -F arch=$ARCH -S finit_module -k modules"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: Set architecture for audit finit_module tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for audit rule entries
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*finit_module.*$
    patterns: '*.rules'
  register: find_finit_module
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use /etc/audit/rules.d/privileged.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_finit_module.matched is defined and find_finit_module.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_finit_module.files | map(attribute=''path'') | list | first }}'
  when:
    - find_finit_module.matched is defined and find_finit_module.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the finit_module rule in rules.d
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S finit_module -k module-change
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the finit_module rule in rules.d on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S finit_module -k module-change
    state: present
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the finit_module rule in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b32 -S finit_module -k module-change
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the finit_module rule in audit.rules when on x86_64
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b64 -S finit_module -k module-change
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_finit
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80712-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit finit_module  oval:ssg-test_32bit_ardm_finit_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_finit_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+finit_module[\s]+|([\s]+|[,])finit_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit finit_module  oval:ssg-test_64bit_ardm_finit_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_finit_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+finit_module[\s]+|([\s]+|[,])finit_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit finit_module  oval:ssg-test_32bit_ardm_finit_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_finit_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+finit_module[\s]+|([\s]+|[,])finit_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit finit_module  oval:ssg-test_64bit_ardm_finit_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_finit_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+finit_module[\s]+|([\s]+|[,])finit_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects Information on Kernel Module Loading - init_modulexccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_init mediumCCE-80713-1

Ensure auditd Collects Information on Kernel Module Loading - init_module

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_init
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_kernel_module_loading_init:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80713-1

References:  5.2.17, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000471-GPOS-00216, SRG-OS-000477-GPOS-00222, SRG-OS-000477-VMM-001970

Description

To capture kernel module loading events, use following line, setting ARCH to either b32 for 32-bit system, or having two lines for both b32 and b64 in case your system is 64-bit:

-a always,exit -F arch=ARCH -S init_module -F key=modules
Place to add the line depends on a way auditd daemon is configured. If it is configured to use the augenrules program (the default), add the line to a file with suffix .rules in the directory /etc/audit/rules.d. If the auditd daemon is configured to use the auditctl utility, add the line to file /etc/audit/audit.rules.

Rationale

The addition of kernel modules can be used to alter the behavior of the kernel and potentially introduce malicious code into kernel space. It is important to have an audit trail of modules that have been introduced into the kernel.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
# Note: 32-bit and 64-bit kernel syscall numbers not always line up =>
#       it's required on a 64-bit system to check also for the presence
#       of 32-bit's equivalent of the corresponding rule.
#       (See `man 7 audit.rules` for details )
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S init_module \(-F key=\|-k \).*"
	GROUP="modules"
	FULL_RULE="-a always,exit -F arch=$ARCH -S init_module -k modules"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: Set architecture for audit init_module tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for audit rule entries
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*init_module.*$
    patterns: '*.rules'
  register: find_init_module
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use /etc/audit/rules.d/privileged.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_init_module.matched is defined and find_init_module.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_init_module.files | map(attribute=''path'') | list | first }}'
  when:
    - find_init_module.matched is defined and find_init_module.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the init_module rule in rules.d
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S init_module -k module-change
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the init_module rule in rules.d on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S init_module -k module-change
    state: present
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the init_module rule in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b32 -S init_module -k module-change
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the init_module rule in audit.rules when on x86_64
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b64 -S init_module -k module-change
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_init
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80713-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit init_module  oval:ssg-test_32bit_ardm_init_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_init_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+init_module[\s]+|([\s]+|[,])init_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit init_module  oval:ssg-test_64bit_ardm_init_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_init_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+init_module[\s]+|([\s]+|[,])init_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit init_module  oval:ssg-test_32bit_ardm_init_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_init_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+init_module[\s]+|([\s]+|[,])init_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit init_module  oval:ssg-test_64bit_ardm_init_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_init_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+init_module[\s]+|([\s]+|[,])init_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects Information on Kernel Module Unloading - delete_modulexccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_delete mediumCCE-80711-5

Ensure auditd Collects Information on Kernel Module Unloading - delete_module

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading_delete
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_kernel_module_loading_delete:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80711-5

References:  5.2.17, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000471-GPOS-00216, SRG-OS-000477-GPOS-00222, SRG-OS-000477-VMM-001970

Description

To capture kernel module unloading events, use following line, setting ARCH to either b32 for 32-bit system, or having two lines for both b32 and b64 in case your system is 64-bit:

-a always,exit -F arch=ARCH -S delete_module -F key=modules
Place to add the line depends on a way auditd daemon is configured. If it is configured to use the augenrules program (the default), add the line to a file with suffix .rules in the directory /etc/audit/rules.d. If the auditd daemon is configured to use the auditctl utility, add the line to file /etc/audit/audit.rules.

Rationale

The removal of kernel modules can be used to alter the behavior of the kernel and potentially introduce malicious code into kernel space. It is important to have an audit trail of modules that have been introduced into the kernel.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
# Note: 32-bit and 64-bit kernel syscall numbers not always line up =>
#       it's required on a 64-bit system to check also for the presence
#       of 32-bit's equivalent of the corresponding rule.
#       (See `man 7 audit.rules` for details )
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S delete_module \(-F key=\|-k \).*"
	GROUP="modules"
	FULL_RULE="-a always,exit -F arch=$ARCH -S delete_module -k modules"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: Set architecture for audit delete_module tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for audit rule entries
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*delete_module.*$
    patterns: '*.rules'
  register: find_delete_module
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use /etc/audit/rules.d/privileged.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_delete_module.matched is defined and find_delete_module.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_delete_module.files | map(attribute=''path'') | list | first }}'
  when:
    - find_delete_module.matched is defined and find_delete_module.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the delete_module rule in rules.d
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S delete_module -k module-change
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the delete_module rule in rules.d on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S delete_module -k module-change
    state: present
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the delete_module rule in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b32 -S delete_module -k module-change
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the delete_module rule in audit.rules when on x86_64
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F arch=b64 -S delete_module -k module-change
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_kernel_module_loading_delete
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80711-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit delete_module  oval:ssg-test_32bit_ardm_delete_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_delete_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+delete_module[\s]+|([\s]+|[,])delete_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit delete_module  oval:ssg-test_64bit_ardm_delete_module_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_delete_module_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+delete_module[\s]+|([\s]+|[,])delete_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit delete_module  oval:ssg-test_32bit_ardm_delete_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_delete_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+delete_module[\s]+|([\s]+|[,])delete_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit delete_module  oval:ssg-test_64bit_ardm_delete_module_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_delete_module_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+delete_module[\s]+|([\s]+|[,])delete_module([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - lchownxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lchown mediumCCE-80693-5

Record Events that Modify the System's Discretionary Access Controls - lchown

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lchown
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_lchown:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80693-5

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S lchown.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit lchown tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_lchown
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_lchown.matched is defined and find_lchown.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_lchown.files | map(attribute=''path'') | list | first }}'
  when:
    - find_lchown.matched is defined and find_lchown.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lchown rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lchown rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lchown rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lchown rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80693-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit lchown  oval:ssg-test_32bit_ardm_lchown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lchown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lchown[\s]+|([\s]+|[,])lchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit lchown  oval:ssg-test_64bit_ardm_lchown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lchown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lchown[\s]+|([\s]+|[,])lchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit lchown  oval:ssg-test_32bit_ardm_lchown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lchown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lchown[\s]+|([\s]+|[,])lchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit lchown  oval:ssg-test_64bit_ardm_lchown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lchown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lchown[\s]+|([\s]+|[,])lchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - setxattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_setxattr mediumCCE-80697-6

Record Events that Modify the System's Discretionary Access Controls - setxattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_setxattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_setxattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80697-6

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S setxattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit setxattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_setxattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_setxattr.matched is defined and find_setxattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_setxattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_setxattr.matched is defined and find_setxattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the setxattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the setxattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the setxattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the setxattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S setxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_setxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80697-6
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit setxattr  oval:ssg-test_32bit_ardm_setxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setxattr[\s]+|([\s]+|[,])setxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit setxattr  oval:ssg-test_64bit_ardm_setxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setxattr[\s]+|([\s]+|[,])setxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit setxattr  oval:ssg-test_32bit_ardm_setxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setxattr[\s]+|([\s]+|[,])setxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit setxattr  oval:ssg-test_64bit_ardm_setxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setxattr[\s]+|([\s]+|[,])setxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fchownxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchown mediumCCE-80689-3

Record Events that Modify the System's Discretionary Access Controls - fchown

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchown
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fchown:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80689-3

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fchown.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fchown tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fchown
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fchown.matched is defined and find_fchown.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fchown.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fchown.matched is defined and find_fchown.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchown rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchown rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchown rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchown rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80689-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fchown  oval:ssg-test_32bit_ardm_fchown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchown[\s]+|([\s]+|[,])fchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fchown  oval:ssg-test_64bit_ardm_fchown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchown[\s]+|([\s]+|[,])fchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fchown  oval:ssg-test_32bit_ardm_fchown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchown[\s]+|([\s]+|[,])fchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fchown  oval:ssg-test_64bit_ardm_fchown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchown[\s]+|([\s]+|[,])fchown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - chownxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chown mediumCCE-80686-9

Record Events that Modify the System's Discretionary Access Controls - chown

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chown
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_chown:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80686-9

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S chown.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit chown tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_chown
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_chown.matched is defined and find_chown.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_chown.files | map(attribute=''path'') | list | first }}'
  when:
    - find_chown.matched is defined and find_chown.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chown rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chown rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chown rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chown rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S chown -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chown
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80686-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit chown  oval:ssg-test_32bit_ardm_chown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_chown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+chown[\s]+|([\s]+|[,])chown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit chown  oval:ssg-test_64bit_ardm_chown_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_chown_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+chown[\s]+|([\s]+|[,])chown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit chown  oval:ssg-test_32bit_ardm_chown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_chown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+chown[\s]+|([\s]+|[,])chown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit chown  oval:ssg-test_64bit_ardm_chown_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_chown_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+chown[\s]+|([\s]+|[,])chown([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fchownatxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchownat mediumCCE-80690-1

Record Events that Modify the System's Discretionary Access Controls - fchownat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchownat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fchownat:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80690-1

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fchownat.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fchownat tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fchownat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fchownat.matched is defined and find_fchownat.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fchownat.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fchownat.matched is defined and find_fchownat.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchownat rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchownat rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchownat rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchownat rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchownat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80690-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fchownat  oval:ssg-test_32bit_ardm_fchownat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchownat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchownat[\s]+|([\s]+|[,])fchownat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fchownat  oval:ssg-test_64bit_ardm_fchownat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchownat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchownat[\s]+|([\s]+|[,])fchownat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fchownat  oval:ssg-test_32bit_ardm_fchownat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchownat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchownat[\s]+|([\s]+|[,])fchownat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fchownat  oval:ssg-test_64bit_ardm_fchownat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchownat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchownat[\s]+|([\s]+|[,])fchownat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fremovexattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fremovexattr mediumCCE-80691-9

Record Events that Modify the System's Discretionary Access Controls - fremovexattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fremovexattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fremovexattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80691-9

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root.

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:

-a always,exit -F arch=b32 -S fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


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:
-a always,exit -F arch=b32 -S fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fremovexattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fremovexattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fremovexattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fremovexattr.matched is defined and find_fremovexattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fremovexattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fremovexattr.matched is defined and find_fremovexattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fremovexattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fremovexattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fremovexattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fremovexattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80691-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fremovexattr  oval:ssg-test_32bit_ardm_fremovexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fremovexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fremovexattr[\s]+|([\s]+|[,])fremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fremovexattr  oval:ssg-test_64bit_ardm_fremovexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fremovexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fremovexattr[\s]+|([\s]+|[,])fremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fremovexattr  oval:ssg-test_32bit_ardm_fremovexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fremovexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fremovexattr[\s]+|([\s]+|[,])fremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fremovexattr  oval:ssg-test_64bit_ardm_fremovexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fremovexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fremovexattr[\s]+|([\s]+|[,])fremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fsetxattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fsetxattr mediumCCE-80692-7

Record Events that Modify the System's Discretionary Access Controls - fsetxattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fsetxattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fsetxattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80692-7

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S fsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S fsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fsetxattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fsetxattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fsetxattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fsetxattr.matched is defined and find_fsetxattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fsetxattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fsetxattr.matched is defined and find_fsetxattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fsetxattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fsetxattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fsetxattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fsetxattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80692-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fsetxattr  oval:ssg-test_32bit_ardm_fsetxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fsetxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fsetxattr[\s]+|([\s]+|[,])fsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fsetxattr  oval:ssg-test_64bit_ardm_fsetxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fsetxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fsetxattr[\s]+|([\s]+|[,])fsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fsetxattr  oval:ssg-test_32bit_ardm_fsetxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fsetxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fsetxattr[\s]+|([\s]+|[,])fsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fsetxattr  oval:ssg-test_64bit_ardm_fsetxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fsetxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fsetxattr[\s]+|([\s]+|[,])fsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fchmodatxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchmodat mediumCCE-80688-5

Record Events that Modify the System's Discretionary Access Controls - fchmodat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchmodat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fchmodat:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80688-5

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fchmodat.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fchmodat tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fchmodat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fchmodat.matched is defined and find_fchmodat.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fchmodat.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fchmodat.matched is defined and find_fchmodat.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmodat rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmodat rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmodat rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmodat rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmodat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80688-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fchmodat  oval:ssg-test_32bit_ardm_fchmodat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchmodat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchmodat[\s]+|([\s]+|[,])fchmodat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fchmodat  oval:ssg-test_64bit_ardm_fchmodat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchmodat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchmodat[\s]+|([\s]+|[,])fchmodat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fchmodat  oval:ssg-test_32bit_ardm_fchmodat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchmodat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchmodat[\s]+|([\s]+|[,])fchmodat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fchmodat  oval:ssg-test_64bit_ardm_fchmodat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchmodat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchmodat[\s]+|([\s]+|[,])fchmodat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - lsetxattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lsetxattr mediumCCE-80695-0

Record Events that Modify the System's Discretionary Access Controls - lsetxattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lsetxattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_lsetxattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80695-0

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S lsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S lsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S lsetxattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S lsetxattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit lsetxattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_lsetxattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_lsetxattr.matched is defined and find_lsetxattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_lsetxattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_lsetxattr.matched is defined and find_lsetxattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lsetxattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S lsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lsetxattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S lsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lsetxattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S lsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lsetxattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S lsetxattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lsetxattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80695-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit lsetxattr  oval:ssg-test_32bit_ardm_lsetxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lsetxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lsetxattr[\s]+|([\s]+|[,])lsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit lsetxattr  oval:ssg-test_64bit_ardm_lsetxattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lsetxattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lsetxattr[\s]+|([\s]+|[,])lsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit lsetxattr  oval:ssg-test_32bit_ardm_lsetxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lsetxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lsetxattr[\s]+|([\s]+|[,])lsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit lsetxattr  oval:ssg-test_64bit_ardm_lsetxattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lsetxattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lsetxattr[\s]+|([\s]+|[,])lsetxattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - removexattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_removexattr mediumCCE-80696-8

Record Events that Modify the System's Discretionary Access Controls - removexattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_removexattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_removexattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80696-8

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root.

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:

-a always,exit -F arch=b32 -S removexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S removexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


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:
-a always,exit -F arch=b32 -S removexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S removexattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S removexattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S removexattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit removexattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_removexattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_removexattr.matched is defined and find_removexattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_removexattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_removexattr.matched is defined and find_removexattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the removexattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S removexattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the removexattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S removexattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the removexattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S removexattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the removexattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S removexattr -F auid>=1000 -F auid!=unset -F
      key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_removexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80696-8
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit removexattr  oval:ssg-test_32bit_ardm_removexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_removexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+removexattr[\s]+|([\s]+|[,])removexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit removexattr  oval:ssg-test_64bit_ardm_removexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_removexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+removexattr[\s]+|([\s]+|[,])removexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit removexattr  oval:ssg-test_32bit_ardm_removexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_removexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+removexattr[\s]+|([\s]+|[,])removexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit removexattr  oval:ssg-test_64bit_ardm_removexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_removexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+removexattr[\s]+|([\s]+|[,])removexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - chmodxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chmod mediumCCE-80685-1

Record Events that Modify the System's Discretionary Access Controls - chmod

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chmod
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_chmod:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80685-1

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S chmod.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit chmod tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_chmod
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_chmod.matched is defined and find_chmod.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_chmod.files | map(attribute=''path'') | list | first }}'
  when:
    - find_chmod.matched is defined and find_chmod.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chmod rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chmod rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chmod rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the chmod rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S chmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_chmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80685-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit chmod  oval:ssg-test_32bit_ardm_chmod_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_chmod_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+chmod[\s]+|([\s]+|[,])chmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit chmod  oval:ssg-test_64bit_ardm_chmod_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_chmod_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+chmod[\s]+|([\s]+|[,])chmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit chmod  oval:ssg-test_32bit_ardm_chmod_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_chmod_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+chmod[\s]+|([\s]+|[,])chmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit chmod  oval:ssg-test_64bit_ardm_chmod_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_chmod_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+chmod[\s]+|([\s]+|[,])chmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - fchmodxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchmod mediumCCE-80687-7

Record Events that Modify the System's Discretionary Access Controls - fchmod

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_fchmod
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_fchmod:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80687-7

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root. 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:

-a always,exit -F arch=b32 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
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:
-a always,exit -F arch=b32 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S fchmod.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit fchmod tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_fchmod
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_fchmod.matched is defined and find_fchmod.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_fchmod.files | map(attribute=''path'') | list | first }}'
  when:
    - find_fchmod.matched is defined and find_fchmod.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmod rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmod rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmod rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the fchmod rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S fchmod -F auid>=1000 -F auid!=unset -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_fchmod
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80687-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit fchmod  oval:ssg-test_32bit_ardm_fchmod_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchmod_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchmod[\s]+|([\s]+|[,])fchmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit fchmod  oval:ssg-test_64bit_ardm_fchmod_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchmod_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchmod[\s]+|([\s]+|[,])fchmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit fchmod  oval:ssg-test_32bit_ardm_fchmod_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_fchmod_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+fchmod[\s]+|([\s]+|[,])fchmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit fchmod  oval:ssg-test_64bit_ardm_fchmod_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_fchmod_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+fchmod[\s]+|([\s]+|[,])fchmod([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Events that Modify the System's Discretionary Access Controls - lremovexattrxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lremovexattr mediumCCE-80694-3

Record Events that Modify the System's Discretionary Access Controls - lremovexattr

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_dac_modification_lremovexattr
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_dac_modification_lremovexattr:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80694-3

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5, SRG-OS-000064-GPOS-00033, SRG-OS-000392-GPOS-00172, SRG-OS-000458-GPOS-00203, SRG-OS-000458-VMM-001810, SRG-OS-000474-VMM-001940

Description

At a minimum, the audit system should collect file permission changes for all users and root.

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:

-a always,exit -F arch=b32 -S lremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


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:
-a always,exit -F arch=b32 -S lremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod


If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S lremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod

Rationale

The changing of file permissions could indicate that a user is attempting to gain access to information that would otherwise be disallowed. Auditing DAC modifications can facilitate the identification of patterns of abuse among both authorized and unauthorized users.

Warnings
warning  Note that these rules can be configured in a number of ways while still achieving the desired effect. Here the system calls have been placed independent of other system calls. Grouping these system calls with others as identifying earlier in this guide is more efficient.


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S lremovexattr.*"
	GROUP="perm_mod"
	FULL_RULE="-a always,exit -F arch=$ARCH -S lremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod"

	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit lremovexattr tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=perm_mod$
    patterns: '*.rules'
  register: find_lremovexattr
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_lremovexattr.matched is defined and find_lremovexattr.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_lremovexattr.files | map(attribute=''path'') | list | first }}'
  when:
    - find_lremovexattr.matched is defined and find_lremovexattr.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lremovexattr rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S lremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lremovexattr rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S lremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lremovexattr rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S lremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the lremovexattr rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S lremovexattr -F auid>=1000 -F auid!=unset
      -F key=perm_mod
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_dac_modification_lremovexattr
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80694-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit lremovexattr  oval:ssg-test_32bit_ardm_lremovexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lremovexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lremovexattr[\s]+|([\s]+|[,])lremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit lremovexattr  oval:ssg-test_64bit_ardm_lremovexattr_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lremovexattr_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lremovexattr[\s]+|([\s]+|[,])lremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit lremovexattr  oval:ssg-test_32bit_ardm_lremovexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_lremovexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+lremovexattr[\s]+|([\s]+|[,])lremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit lremovexattr  oval:ssg-test_64bit_ardm_lremovexattr_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_lremovexattr_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+lremovexattr[\s]+|([\s]+|[,])lremovexattr([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects Information on the Use of Privileged Commandsxccdf_org.ssgproject.content_rule_audit_rules_privileged_commands mediumCCE-80724-8

Ensure auditd Collects Information on the Use of Privileged Commands

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_privileged_commands
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_privileged_commands:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80724-8

References:  5.2.10, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO08.04, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.05, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-002234, 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.5, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.3.4.5.9, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 3.9, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.1, A.16.1.2, A.16.1.3, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.3, A.6.2.1, A.6.2.2, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-2, DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, DE.DP-4, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, RS.CO-2, Req-10.2.2, SRG-OS-000327-GPOS-00127, SRG-OS-000471-VMM-001910

Description

At a minimum, the audit system should collect the execution of privileged commands for all users and root. To find the relevant setuid / setgid programs, run the following command for each local partition PART:

$ sudo find PART -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null
If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add a line of the following form to a file with suffix .rules in the directory /etc/audit/rules.d for each setuid / setgid program on the system, replacing the SETUID_PROG_PATH part with the full path of that setuid / setgid program in the list:
-a always,exit -F path=SETUID_PROG_PATH -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add a line of the following form to /etc/audit/audit.rules for each setuid / setgid program on the system, replacing the SETUID_PROG_PATH part with the full path of that setuid / setgid program in the list:
-a always,exit -F path=SETUID_PROG_PATH -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes

Rationale

Misuse of privileged functions, either intentionally or unintentionally by authorized users, or by unauthorized external entities that have compromised system accounts, is a serious and ongoing concern and can have significant adverse impacts on organizations. Auditing the use of privileged functions is one way to detect such misuse and identify the risk from insider and advanced persistent threast.

Privileged programs are subject to escalation-of-privilege attacks, which attempt to subvert their normal role of providing some necessary but limited capability. As such, motivation exists to monitor these programs for unusual activity.

Warnings
warning  This rule checks for multiple syscalls related to privileged commands; it was written with DISA STIG in mind. Other policies should use a separate rule for each syscall that needs to be checked. For example:
  • audit_rules_privileged_commands_su
  • audit_rules_privileged_commands_umount
  • audit_rules_privileged_commands_passwd


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to perform remediation for 'audit_rules_privileged_commands' rule
#
# Expects two arguments:
#
# audit_tool		tool used to load audit rules
# 			One of 'auditctl' or 'augenrules'
#
# min_auid		Minimum original ID the user logged in with
#
# Example Call(s):
#
#      perform_audit_rules_privileged_commands_remediation "auditctl" "500"
#      perform_audit_rules_privileged_commands_remediation "augenrules"	"1000"
#
function perform_audit_rules_privileged_commands_remediation {
#
# Load function arguments into local variables
local tool="$1"
local min_auid="$2"

# Check sanity of the input
if [ $# -ne "2" ]
then
	echo "Usage: perform_audit_rules_privileged_commands_remediation 'auditctl | augenrules' '500 | 1000'"
	echo "Aborting."
	exit 1
fi

declare -a files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then:
# * add '/etc/audit/audit.rules'to the list of files to be inspected,
# * specify '/etc/audit/audit.rules' as the output audit file, where
#   missing rules should be inserted
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect=("/etc/audit/audit.rules")
	output_audit_file="/etc/audit/audit.rules"
#
# If the audit tool is 'augenrules', then:
# * add '/etc/audit/rules.d/*.rules' to the list of files to be inspected
#   (split by newline),
# * specify /etc/audit/rules.d/privileged.rules' as the output file, where
#   missing rules should be inserted
elif [ "$tool" == 'augenrules' ]
then
	readarray -t files_to_inspect < <(find /etc/audit/rules.d -maxdepth 1 -type f -name '*.rules' -print)
	output_audit_file="/etc/audit/rules.d/privileged.rules"
fi

# Obtain the list of SUID/SGID binaries on the particular system (split by newline)
# into privileged_binaries array
privileged_binaries=()
readarray -t privileged_binaries < <(find / -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null)

# Keep list of SUID/SGID binaries that have been already handled within some previous iteration
declare -a sbinaries_to_skip=()

# For each found sbinary in privileged_binaries list
for sbinary in "${privileged_binaries[@]}"
do

	# Check if this sbinary wasn't already handled in some of the previous sbinary iterations
	# Return match only if whole sbinary definition matched (not in the case just prefix matched!!!)
	if [[ $(sed -ne "\|${sbinary}|p" <<< "${sbinaries_to_skip[*]}") ]]
	then
		# If so, don't process it second time & go to process next sbinary
		continue
	fi

	# Reset the counter of inspected files when starting to check
	# presence of existing audit rule for new sbinary
	local count_of_inspected_files=0

	# Define expected rule form for this binary
	expected_rule="-a always,exit -F path=${sbinary} -F perm=x -F auid>=${min_auid} -F auid!=unset -k privileged"

	# If list of audit rules files to be inspected is empty, just add new rule and move on to next binary
	if [[ ${#files_to_inspect[@]} -eq 0 ]]; then
		echo "$expected_rule" >> "$output_audit_file"
		continue
	fi

	# Replace possible slash '/' character in sbinary definition so we could use it in sed expressions below
	sbinary_esc=${sbinary//$'/'/$'\/'}

	# For each audit rules file from the list of files to be inspected
	for afile in "${files_to_inspect[@]}"
	do

		# Search current audit rules file's content for match. Match criteria:
		# * existing rule is for the same SUID/SGID binary we are currently processing (but
		#   can contain multiple -F path= elements covering multiple SUID/SGID binaries)
		# * existing rule contains all arguments from expected rule form (though can contain
		#   them in arbitrary order)
	
		base_search=$(sed -e '/-a always,exit/!d' -e '/-F path='"${sbinary_esc}"'[^[:graph:]]/!d'		\
				-e '/-F path=[^[:space:]]\+/!d'   -e '/-F perm=.*/!d'						\
				-e '/-F auid>='"${min_auid}"'/!d' -e '/-F auid!=\(4294967295\|unset\)/!d'	\
				-e '/-k \|-F key=/!d' "$afile")

		# Increase the count of inspected files for this sbinary
		count_of_inspected_files=$((count_of_inspected_files + 1))

		# Require execute access type to be set for existing audit rule
		exec_access='x'

		# Search current audit rules file's content for presence of rule pattern for this sbinary
		if [[ $base_search ]]
		then

			# Current audit rules file already contains rule for this binary =>
			# Store the exact form of found rule for this binary for further processing
			concrete_rule=$base_search

			# Select all other SUID/SGID binaries possibly also present in the found rule

			readarray -t handled_sbinaries < <(grep -o -e "-F path=[^[:space:]]\+" <<< "$concrete_rule")
			handled_sbinaries=("${handled_sbinaries[@]//-F path=/}")

			# Merge the list of such SUID/SGID binaries found in this iteration with global list ignoring duplicates
			readarray -t sbinaries_to_skip < <(for i in "${sbinaries_to_skip[@]}" "${handled_sbinaries[@]}"; do echo "$i"; done | sort -du)

			# Separate concrete_rule into three sections using hash '#'
			# sign as a delimiter around rule's permission section borders
			concrete_rule="$(echo "$concrete_rule" | sed -n "s/\(.*\)\+\(-F perm=[rwax]\+\)\+/\1#\2#/p")"

			# Split concrete_rule into head, perm, and tail sections using hash '#' delimiter

			rule_head=$(cut -d '#' -f 1 <<< "$concrete_rule")
			rule_perm=$(cut -d '#' -f 2 <<< "$concrete_rule")
			rule_tail=$(cut -d '#' -f 3 <<< "$concrete_rule")

			# Extract already present exact access type [r|w|x|a] from rule's permission section
			access_type=${rule_perm//-F perm=/}

			# Verify current permission access type(s) for rule contain 'x' (execute) permission
			if ! grep -q "$exec_access" <<< "$access_type"
			then

				# If not, append the 'x' (execute) permission to the existing access type bits
				access_type="$access_type$exec_access"
				# Reconstruct the permissions section for the rule
				new_rule_perm="-F perm=$access_type"
				# Update existing rule in current audit rules file with the new permission section
				sed -i "s#${rule_head}\(.*\)${rule_tail}#${rule_head}${new_rule_perm}${rule_tail}#" "$afile"

			fi

		# If the required audit rule for particular sbinary wasn't found yet, insert it under following conditions:
		#
		# * in the "auditctl" mode of operation insert particular rule each time
		#   (because in this mode there's only one file -- /etc/audit/audit.rules to be inspected for presence of this rule),
		#
		# * in the "augenrules" mode of operation insert particular rule only once and only in case we have already
		#   searched all of the files from /etc/audit/rules.d/*.rules location (since that audit rule can be defined
		#   in any of those files and if not, we want it to be inserted only once into /etc/audit/rules.d/privileged.rules file)
		#
		elif [ "$tool" == "auditctl" ] || [[ "$tool" == "augenrules" && $count_of_inspected_files -eq "${#files_to_inspect[@]}" ]]
		then

			# Check if this sbinary wasn't already handled in some of the previous afile iterations
			# Return match only if whole sbinary definition matched (not in the case just prefix matched!!!)
			if [[ ! $(sed -ne "\|${sbinary}|p" <<< "${sbinaries_to_skip[*]}") ]]
			then
				# Current audit rules file's content doesn't contain expected rule for this
				# SUID/SGID binary yet => append it
				echo "$expected_rule" >> "$output_audit_file"
			fi

			continue
		fi

	done

done
}
perform_audit_rules_privileged_commands_remediation "auditctl" "1000"
perform_audit_rules_privileged_commands_remediation "augenrules" "1000"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Search for privileged commands
  shell: find / -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null
  args:
    warn: false
    executable: /bin/bash
  check_mode: false
  register: find_result
  changed_when: false
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_privileged_commands
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80724-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for audit rule entries
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*path={{ item }} .*$
    patterns: '*.rules'
  with_items:
    - '{{ find_result.stdout_lines }}'
  register: files_result
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_privileged_commands
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80724-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - CJIS-5.4.1.1

- name: Overwrites the rule in rules.d
  lineinfile:
    path: '{{ item.1.path }}'
    line: -a always,exit -F path={{ item.0.item }} -F perm=x -F auid>=1000 -F auid!=unset
      -F key=special-config-changes
    create: false
    regexp: ^.*path={{ item.0.item }} .*$
  with_subelements:
    - '{{ files_result.results }}'
    - files
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_privileged_commands
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80724-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - CJIS-5.4.1.1

- name: Adds the rule in rules.d
  lineinfile:
    path: /etc/audit/rules.d/privileged.rules
    line: -a always,exit -F path={{ item.item }} -F perm=x -F auid>=1000 -F auid!=unset
      -F key=special-config-changes
    create: true
  with_items:
    - '{{ files_result.results }}'
  when:
    - files_result.results is defined and item.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_privileged_commands
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80724-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - CJIS-5.4.1.1

- name: Inserts/replaces the rule in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -a always,exit -F path={{ item.item }} -F perm=x -F auid>=1000 -F auid!=unset
      -F key=special-config-changes
    create: true
    regexp: ^.*path={{ item.item }} .*$
  with_items:
    - '{{ files_result.results }}'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_privileged_commands
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80724-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules suid sgid  oval:ssg-test_arpc_suid_sgid_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arpc_suid_sgid_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstanceFilter
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a always,exit (?:-F path=([\S]+) )+-F perm=[r|w]?x -F auid>=1000 -F auid!=(?:4294967295|unset)[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1oval:ssg-state_proper_audit_rule_but_for_unprivileged_command:ste:1

audit augenrules binaries count matches rules count  oval:ssg-test_arpc_bin_count_equals_rules_count_augenrules:tst:1  error

Following items have been found on the system:
Var refValue
oval:ssg-variable_count_of_suid_sgid_binaries_on_system:var:123

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl suid sgid  oval:ssg-test_arpc_suid_sgid_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arpc_suid_sgid_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstanceFilter
/etc/audit/audit.rules^[\s]*-a always,exit (?:-F path=([\S]+) )+-F perm=[r|w]?x -F auid>=1000 -F auid!=(?:4294967295|unset)[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1oval:ssg-state_proper_audit_rule_but_for_unprivileged_command:ste:1

audit auditctl binaries count matches rules count  oval:ssg-test_arpc_bin_count_equals_rules_count_auditctl:tst:1  error

Following items have been found on the system:
Var refValue
oval:ssg-variable_count_of_suid_sgid_binaries_on_system:var:123
Record Attempts to Alter Time Through stimexccdf_org.ssgproject.content_rule_audit_rules_time_stime mediumCCE-80748-7

Record Attempts to Alter Time Through stime

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_time_stime
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_time_stime:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80748-7

References:  4.1.6, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.4.2.b

Description

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 for both 32 bit and 64 bit systems:

-a always,exit -F arch=b32 -S stime -F key=audit_time_rules
Since the 64 bit version of the "stime" system call is not defined in the audit lookup table, the corresponding "-F arch=b64" form of this rule is not expected to be defined on 64 bit systems (the aforementioned "-F arch=b32" stime rule form itself is sufficient for both 32 bit and 64 bit systems). 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 for both 32 bit and 64 bit systems:
-a always,exit -F arch=b32 -S stime -F key=audit_time_rules
Since the 64 bit version of the "stime" system call is not defined in the audit lookup table, the corresponding "-F arch=b64" form of this rule is not expected to be defined on 64 bit systems (the aforementioned "-F arch=b32" stime rule form itself is sufficient for both 32 bit and 64 bit systems). The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined system calls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules

Rationale

Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}


# Function to perform remediation for the 'adjtimex', 'settimeofday', and 'stime' audit
# system calls on RHEL, Fedora or OL systems.
# Remediation performed for both possible tools: 'auditctl' and 'augenrules'.
#
# Note: 'stime' system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
# therefore excluded from the list of time group system calls to be audited on this arch
#
# Example Call:
#
#      perform_audit_adjtimex_settimeofday_stime_remediation
#
function perform_audit_adjtimex_settimeofday_stime_remediation {

# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do

	PATTERN="-a always,exit -F arch=${ARCH} -S .* -k *"
	# Create expected audit group and audit rule form for particular system call & architecture
	if [ ${ARCH} = "b32" ]
	then
		# stime system call is known at 32-bit arch (see e.g "$ ausyscall i386 stime" 's output)
		# so append it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\|stime\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -S stime -k audit_time_rules"
	elif [ ${ARCH} = "b64" ]
	then
		# stime system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
		# therefore don't add it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -k audit_time_rules"
	fi
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

}
perform_audit_adjtimex_settimeofday_stime_remediation

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Perform remediation of Audit rules for stime syscall for x86 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - stime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - stime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_stime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80748-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1
OVAL test results details

32 bit architecture  oval:ssg-test_system_info_architecture_x86:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit stime  oval:ssg-test_32bit_art_stime_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_stime_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+stime[\s]+|([\s]+|[,])stime([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit stime  oval:ssg-test_32bit_art_stime_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_stime_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+stime[\s]+|([\s]+|[,])stime([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record attempts to alter time through adjtimexxccdf_org.ssgproject.content_rule_audit_rules_time_adjtimex mediumCCE-80745-3

Record attempts to alter time through adjtimex

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_time_adjtimex
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_time_adjtimex:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80745-3

References:  4.1.6, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.4.2.b

Description

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:

-a always,exit -F arch=b32 -S adjtimex -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S adjtimex -F key=audit_time_rules
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:
-a always,exit -F arch=b32 -S adjtimex -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S adjtimex -F key=audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules

Rationale

Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}


# Function to perform remediation for the 'adjtimex', 'settimeofday', and 'stime' audit
# system calls on RHEL, Fedora or OL systems.
# Remediation performed for both possible tools: 'auditctl' and 'augenrules'.
#
# Note: 'stime' system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
# therefore excluded from the list of time group system calls to be audited on this arch
#
# Example Call:
#
#      perform_audit_adjtimex_settimeofday_stime_remediation
#
function perform_audit_adjtimex_settimeofday_stime_remediation {

# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do

	PATTERN="-a always,exit -F arch=${ARCH} -S .* -k *"
	# Create expected audit group and audit rule form for particular system call & architecture
	if [ ${ARCH} = "b32" ]
	then
		# stime system call is known at 32-bit arch (see e.g "$ ausyscall i386 stime" 's output)
		# so append it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\|stime\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -S stime -k audit_time_rules"
	elif [ ${ARCH} = "b64" ]
	then
		# stime system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
		# therefore don't add it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -k audit_time_rules"
	fi
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

}
perform_audit_adjtimex_settimeofday_stime_remediation

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_adjtimex
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80745-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for adjtimex for x86 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_adjtimex
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80745-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for adjtimex for x86_64 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - audit_arch == "b64"
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_adjtimex
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80745-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit adjtimex  oval:ssg-test_32bit_art_adjtimex_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_adjtimex_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+adjtimex[\s]+|([\s]+|[,])adjtimex([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit adjtimex  oval:ssg-test_64bit_art_adjtimex_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_adjtimex_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64.*(-S[\s]+adjtimex[\s]+|([\s]+|[,])adjtimex([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit adjtimex  oval:ssg-test_32bit_art_adjtimex_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_adjtimex_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+adjtimex[\s]+|([\s]+|[,])adjtimex([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit adjtimex  oval:ssg-test_64bit_art_adjtimex_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_adjtimex_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64.*(-S[\s]+adjtimex[\s]+|([\s]+|[,])adjtimex([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record Attempts to Alter Time Through clock_settimexccdf_org.ssgproject.content_rule_audit_rules_time_clock_settime mediumCCE-80746-1

Record Attempts to Alter Time Through clock_settime

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_time_clock_settime
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_time_clock_settime:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80746-1

References:  4.1.6, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.4.2.b

Description

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:

-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -F key=time-change
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -F key=time-change
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:
-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -F key=time-change
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -F key=time-change
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules

Rationale

Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S clock_settime -F a0=.* \(-F key=\|-k \).*"
	GROUP="clock_settime"
	FULL_RULE="-a always,exit -F arch=$ARCH -S clock_settime -F a0=0x0 -k time-change"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_clock_settime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80746-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for clock_settime for x86 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key time-change
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)time-change$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/time-change.rules as the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/time-change.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_clock_settime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80746-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for clock_settime for x86_64 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key time-change
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)time-change$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/time-change.rules as the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/time-change.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - audit_arch == "b64"
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_clock_settime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80746-1
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit clock_settime  oval:ssg-test_32bit_art_clock_settime_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_clock_settime_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+(-S[\s]+clock_settime[\s]+|([\s]+|[,])clock_settime([\s]+|[,]))-F[\s]+a0=(?:0x)?0[\s]+(?:-F[\s]+key=|-k[\s]+)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit clock_settime  oval:ssg-test_64bit_art_clock_settime_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_clock_settime_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+(-S[\s]+clock_settime[\s]+|([\s]+|[,])clock_settime([\s]+|[,]))-F[\s]+a0=(?:0x)?0[\s]+(?:-F[\s]+key=|-k[\s]+)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit clock_settime  oval:ssg-test_32bit_art_clock_settime_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_clock_settime_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+(-S[\s]+clock_settime[\s]+|([\s]+|[,])clock_settime([\s]+|[,]))-F[\s]+a0=(?:0x)?0[\s]+(?:-F[\s]+key=|-k[\s]+)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit clock_settime  oval:ssg-test_64bit_art_clock_settime_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_clock_settime_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+(-S[\s]+clock_settime[\s]+|([\s]+|[,])clock_settime([\s]+|[,]))-F[\s]+a0=(?:0x)?0[\s]+(?:-F[\s]+key=|-k[\s]+)[\S]+[\s]*$1
Record Attempts to Alter the localtime Filexccdf_org.ssgproject.content_rule_audit_rules_time_watch_localtime mediumCCE-80749-5

Record Attempts to Alter the localtime File

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_time_watch_localtime
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_time_watch_localtime:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80749-5

References:  4.1.6, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.4.2.b

Description

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:

-w /etc/localtime -p wa -k audit_time_rules
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:
-w /etc/localtime -p wa -k audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport and should always be used.

Rationale

Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
fix_audit_watch_rule "augenrules" "/etc/localtime" "wa" "audit_time_rules"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Check if watch rule for /etc/localtime already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/localtime\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key audit_time_rules
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_time_rules.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/localtime in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/localtime -p wa -k audit_time_rules
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/localtime already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/localtime\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/localtime in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/localtime -p wa -k audit_time_rules
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_watch_localtime
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80749-5
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit /etc/localtime watch augenrules  oval:ssg-test_artw_etc_localtime_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_artw_etc_localtime_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-w[\s]+\/etc\/localtime[\s]+-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit /etc/localtime watch auditctl  oval:ssg-test_artw_etc_localtime_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_artw_etc_localtime_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-w[\s]+\/etc\/localtime[\s]+-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Record attempts to alter time through settimeofdayxccdf_org.ssgproject.content_rule_audit_rules_time_settimeofday mediumCCE-80747-9

Record attempts to alter time through settimeofday

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_time_settimeofday
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_time_settimeofday:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80747-9

References:  4.1.6, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.4.2.b

Description

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:

-a always,exit -F arch=b32 -S settimeofday -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S settimeofday -F key=audit_time_rules
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:
-a always,exit -F arch=b32 -S settimeofday -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S settimeofday -F key=audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules

Rationale

Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}


# Function to perform remediation for the 'adjtimex', 'settimeofday', and 'stime' audit
# system calls on RHEL, Fedora or OL systems.
# Remediation performed for both possible tools: 'auditctl' and 'augenrules'.
#
# Note: 'stime' system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
# therefore excluded from the list of time group system calls to be audited on this arch
#
# Example Call:
#
#      perform_audit_adjtimex_settimeofday_stime_remediation
#
function perform_audit_adjtimex_settimeofday_stime_remediation {

# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do

	PATTERN="-a always,exit -F arch=${ARCH} -S .* -k *"
	# Create expected audit group and audit rule form for particular system call & architecture
	if [ ${ARCH} = "b32" ]
	then
		# stime system call is known at 32-bit arch (see e.g "$ ausyscall i386 stime" 's output)
		# so append it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\|stime\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -S stime -k audit_time_rules"
	elif [ ${ARCH} = "b64" ]
	then
		# stime system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
		# therefore don't add it to the list of time group system calls to be audited
		GROUP="\(adjtimex\|settimeofday\)"
		FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -k audit_time_rules"
	fi
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

}
perform_audit_adjtimex_settimeofday_stime_remediation

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_settimeofday
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80747-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for settimeofday for x86 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_settimeofday
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80747-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1

- name: Perform remediation of Audit rules for settimeofday for x86_64 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - audit_arch == "b64"
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_time_settimeofday
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80747-9
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.4.2.b
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit settimeofday  oval:ssg-test_32bit_art_settimeofday_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_settimeofday_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+settimeofday[\s]+|([\s]+|[,])settimeofday([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit settimeofday  oval:ssg-test_64bit_art_settimeofday_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_settimeofday_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64.*(-S[\s]+settimeofday[\s]+|([\s]+|[,])settimeofday([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit settimeofday  oval:ssg-test_32bit_art_settimeofday_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_art_settimeofday_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32.*(-S[\s]+settimeofday[\s]+|([\s]+|[,])settimeofday([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit settimeofday  oval:ssg-test_64bit_art_settimeofday_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_art_settimeofday_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64.*(-S[\s]+settimeofday[\s]+|([\s]+|[,])settimeofday([\s]+|[,])).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects File Deletion Events by User - rmdirxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_rmdir mediumCCE-80705-7

Ensure auditd Collects File Deletion Events by User - rmdir

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_rmdir
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_file_deletion_events_rmdir:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80705-7

References:  5.2.14, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-000366, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.4, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.1.1, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.MA-2, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000466-GPOS-00210, SRG-OS-000467-GPOS-00210, SRG-OS-000468-GPOS-00212, SRG-OS-000392-GPOS-00172, SRG-OS-000466-VMM-001870, SRG-OS-000468-VMM-001890

Description

At a minimum, the audit system should collect file deletion events for all users and root. 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, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S rmdir -F auid>=1000 -F auid!=unset -F key=delete
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, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S rmdir -F auid>=1000 -F auid!=unset -F key=delete

Rationale

Auditing file deletions will create an audit trail for files that are removed from the system. The audit trail could aid in system troubleshooting, as well as, detecting malicious processes that attempt to delete log files to conceal their presence.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S rmdir.*"
	GROUP="delete"
	FULL_RULE="-a always,exit -F arch=$ARCH -S rmdir -F auid>=1000 -F auid!=unset -F key=delete"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit rmdir tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=delete$
    patterns: '*.rules'
  register: find_rmdir
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/delete.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/delete.rules
  when:
    - find_rmdir.matched is defined and find_rmdir.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_rmdir.files | map(attribute=''path'') | list | first }}'
  when:
    - find_rmdir.matched is defined and find_rmdir.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rmdir rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S rmdir -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rmdir rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S rmdir -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rmdir rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S rmdir -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rmdir rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S rmdir -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rmdir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80705-7
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit rmdir  oval:ssg-test_32bit_ardm_rmdir_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_rmdir_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+rmdir[\s]+|([\s]+|[,])rmdir([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit rmdir  oval:ssg-test_64bit_ardm_rmdir_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_rmdir_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+rmdir[\s]+|([\s]+|[,])rmdir([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit rmdir  oval:ssg-test_32bit_ardm_rmdir_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_rmdir_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+rmdir[\s]+|([\s]+|[,])rmdir([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit rmdir  oval:ssg-test_64bit_ardm_rmdir_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_rmdir_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+rmdir[\s]+|([\s]+|[,])rmdir([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects File Deletion Events by User - renamexccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_rename mediumCCE-80703-2

Ensure auditd Collects File Deletion Events by User - rename

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_rename
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_file_deletion_events_rename:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80703-2

References:  5.2.14, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-000366, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.4, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.1.1, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.MA-2, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000466-GPOS-00210, SRG-OS-000467-GPOS-00210, SRG-OS-000468-GPOS-00212, SRG-OS-000392-GPOS-00172, SRG-OS-000466-VMM-001870, SRG-OS-000468-VMM-001890

Description

At a minimum, the audit system should collect file deletion events for all users and root. 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, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S rename -F auid>=1000 -F auid!=unset -F key=delete
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, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S rename -F auid>=1000 -F auid!=unset -F key=delete

Rationale

Auditing file deletions will create an audit trail for files that are removed from the system. The audit trail could aid in system troubleshooting, as well as, detecting malicious processes that attempt to delete log files to conceal their presence.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S rename.*"
	GROUP="delete"
	FULL_RULE="-a always,exit -F arch=$ARCH -S rename -F auid>=1000 -F auid!=unset -F key=delete"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit rename tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=delete$
    patterns: '*.rules'
  register: find_rename
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/delete.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/delete.rules
  when:
    - find_rename.matched is defined and find_rename.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_rename.files | map(attribute=''path'') | list | first }}'
  when:
    - find_rename.matched is defined and find_rename.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rename rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S rename -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rename rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S rename -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rename rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S rename -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the rename rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S rename -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_rename
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80703-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit rename  oval:ssg-test_32bit_ardm_rename_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_rename_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+rename[\s]+|([\s]+|[,])rename([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit rename  oval:ssg-test_64bit_ardm_rename_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_rename_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+rename[\s]+|([\s]+|[,])rename([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit rename  oval:ssg-test_32bit_ardm_rename_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_rename_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+rename[\s]+|([\s]+|[,])rename([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit rename  oval:ssg-test_64bit_ardm_rename_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_rename_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+rename[\s]+|([\s]+|[,])rename([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects File Deletion Events by User - unlinkatxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_unlinkat mediumCCE-80707-3

Ensure auditd Collects File Deletion Events by User - unlinkat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_unlinkat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_file_deletion_events_unlinkat:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80707-3

References:  5.2.14, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-000366, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.4, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.1.1, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.MA-2, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000466-GPOS-00210, SRG-OS-000467-GPOS-00210, SRG-OS-000468-GPOS-00212, SRG-OS-000392-GPOS-00172, SRG-OS-000466-VMM-001870, SRG-OS-000468-VMM-001890

Description

At a minimum, the audit system should collect file deletion events for all users and root. 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, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete
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, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete

Rationale

Auditing file deletions will create an audit trail for files that are removed from the system. The audit trail could aid in system troubleshooting, as well as, detecting malicious processes that attempt to delete log files to conceal their presence.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S unlinkat.*"
	GROUP="delete"
	FULL_RULE="-a always,exit -F arch=$ARCH -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit unlinkat tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=delete$
    patterns: '*.rules'
  register: find_unlinkat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/delete.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/delete.rules
  when:
    - find_unlinkat.matched is defined and find_unlinkat.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_unlinkat.files | map(attribute=''path'') | list | first }}'
  when:
    - find_unlinkat.matched is defined and find_unlinkat.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the unlinkat rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the unlinkat rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the unlinkat rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the unlinkat rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S unlinkat -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_unlinkat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80707-3
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit unlinkat  oval:ssg-test_32bit_ardm_unlinkat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_unlinkat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+unlinkat[\s]+|([\s]+|[,])unlinkat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit unlinkat  oval:ssg-test_64bit_ardm_unlinkat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_unlinkat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+unlinkat[\s]+|([\s]+|[,])unlinkat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit unlinkat  oval:ssg-test_32bit_ardm_unlinkat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_unlinkat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+unlinkat[\s]+|([\s]+|[,])unlinkat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit unlinkat  oval:ssg-test_64bit_ardm_unlinkat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_unlinkat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+unlinkat[\s]+|([\s]+|[,])unlinkat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects File Deletion Events by User - renameatxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_renameat mediumCCE-80704-0

Ensure auditd Collects File Deletion Events by User - renameat

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_file_deletion_events_renameat
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_file_deletion_events_renameat:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80704-0

References:  5.2.14, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000172, CCI-000366, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.4, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.1.1, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.MA-2, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.7, SRG-OS-000466-GPOS-00210, SRG-OS-000467-GPOS-00210, SRG-OS-000468-GPOS-00212, SRG-OS-000392-GPOS-00172, SRG-OS-000466-VMM-001870, SRG-OS-000468-VMM-001890

Description

At a minimum, the audit system should collect file deletion events for all users and root. 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, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S renameat -F auid>=1000 -F auid!=unset -F key=delete
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, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S renameat -F auid>=1000 -F auid!=unset -F key=delete

Rationale

Auditing file deletions will create an audit trail for files that are removed from the system. The audit trail could aid in system troubleshooting, as well as, detecting malicious processes that attempt to delete log files to conceal their presence.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S renameat.*"
	GROUP="delete"
	FULL_RULE="-a always,exit -F arch=$ARCH -S renameat -F auid>=1000 -F auid!=unset -F key=delete"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit renameat tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Search /etc/audit/rules.d for other DAC audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=delete$
    patterns: '*.rules'
  register: find_renameat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: If existing DAC ruleset not found, use /etc/audit/rules.d/delete.rules as
    the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/delete.rules
  when:
    - find_renameat.matched is defined and find_renameat.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_renameat.files | map(attribute=''path'') | list | first }}'
  when:
    - find_renameat.matched is defined and find_renameat.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the renameat rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S renameat -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the renameat rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S renameat -F auid>=1000 -F auid!=unset -F key=delete
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the renameat rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S renameat -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7

- name: Inserts/replaces the renameat rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S renameat -F auid>=1000 -F auid!=unset -F key=delete
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_file_deletion_events_renameat
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80704-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit renameat  oval:ssg-test_32bit_ardm_renameat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_renameat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+renameat[\s]+|([\s]+|[,])renameat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit renameat  oval:ssg-test_64bit_ardm_renameat_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_renameat_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+renameat[\s]+|([\s]+|[,])renameat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit renameat  oval:ssg-test_32bit_ardm_renameat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_renameat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+renameat[\s]+|([\s]+|[,])renameat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit renameat  oval:ssg-test_64bit_ardm_renameat_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_renameat_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+renameat[\s]+|([\s]+|[,])renameat([\s]+|[,])))(?:.*-F\s+auid>=1000[\s]+)(?:.*-F\s+auid!=(?:4294967295|unset)[\s]+).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
Ensure auditd Collects Information on Exporting to Media (successful)xccdf_org.ssgproject.content_rule_audit_rules_media_export mediumCCE-80722-2

Ensure auditd Collects Information on Exporting to Media (successful)

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_media_export
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_media_export:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80722-2

References:  5.2.13, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000135, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.2.7, SRG-OS-000042-GPOS-00020, SRG-OS-000392-GPOS-00172

Description

At a minimum, the audit system should collect media exportation events for all users and root. 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, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S mount -F auid>=1000 -F auid!=unset -F key=export
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, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S mount -F auid>=1000 -F auid!=unset -F key=export

Rationale

The unauthorized exportation of data to external media could result in an information leak where classified information, Privacy Act information, and intellectual property could be lost. An audit trail should be created each time a filesystem is mounted to help identify and guard against information loss.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S .* -F auid>=1000 -F auid!=unset -k *"
	GROUP="mount"
	FULL_RULE="-a always,exit -F arch=$ARCH -S mount -F auid>=1000 -F auid!=unset -k export"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit media export tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Check if the rule for x86_64 is already present in /etc/audit/rules.d/*
  find:
    paths: /etc/audit/rules.d/
    contains: ^\s*-a\s+always,exit\s+-F\s+arch=b64\s+-S\s+mount\s+-F\s+auid>=1000\s+-F\s+auid!=unset(\s|$)+
    patterns: '*.rules'
  register: find_existing_media_export_64_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Check if the rule for x86 is already present in /etc/audit/rules.d/*
  find:
    paths: /etc/audit/rules.d/
    contains: ^\s*-a\s+always,exit\s+-F\s+arch=b32\s+-S\s+mount\s+-F\s+auid>=1000\s+-F\s+auid!=unset(\s|$)+
    patterns: '*.rules'
  register: find_existing_media_export_32_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Check if the rule for x86_64 is already present in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-a\s+always,exit\s+-F\s+arch=b64\s+-S\s+mount\s+-F\s+auid>=1000\s+-F\s+auid!=unset(\s|$)+
    patterns: audit.rules
  register: find_existing_media_export_64_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Check if the rule for x86 is already present in /etc/audit/rules.d/*
  find:
    paths: /etc/audit/
    contains: ^\s*-a\s+always,exit\s+-F\s+arch=b32\s+-S\s+mount\s+-F\s+auid>=1000\s+-F\s+auid!=unset(\s|$)+
    patterns: audit.rules
  register: find_existing_media_export_32_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other media export audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -F key=export$
    patterns: '*.rules'
  register: find_mount
  when:
    - (find_existing_media_export_32_rules_d is defined and find_existing_media_export_32_rules_d.matched
      == 0) or (find_existing_media_export_64_rules_d is defined and find_existing_media_export_64_rules_d.matched
      == 0)
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: If existing media export ruleset not found, use /etc/audit/rules.d/export.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/export.rules
  when:
    - find_mount.matched is defined and find_mount.matched == 0 and ((find_existing_media_export_32_rules_d
      is defined and find_existing_media_export_32_rules_d.matched == 0) or (find_existing_media_export_64_rules_d
      is defined and find_existing_media_export_64_rules_d.matched == 0))
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_mount.files | map(attribute=''path'') | list | first }}'
  when:
    - find_mount.matched is defined and find_mount.matched > 0 and ((find_existing_media_export_32_rules_d
      is defined and find_existing_media_export_32_rules_d.matched == 0) or (find_existing_media_export_64_rules_d
      is defined and find_existing_media_export_64_rules_d.matched == 0))
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Inserts/replaces the media export rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=unset -F key=export
    create: true
  when:
    - find_existing_media_export_32_rules_d is defined and find_existing_media_export_32_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Inserts/replaces the media export rule in rules.d when on x86_64
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=unset -F key=export
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64' and find_existing_media_export_64_rules_d
      is defined and find_existing_media_export_64_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Inserts/replaces the media export rule in /etc/audit/audit.rules when on x86
  lineinfile:
    line: -a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=unset -F key=export
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_media_export_32_audit_rules is defined and find_existing_media_export_32_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1

- name: Inserts/replaces the media export rule in audit.rules when on x86_64
  lineinfile:
    line: -a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=unset -F key=export
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - audit_arch is defined and audit_arch == 'b64' and find_existing_media_export_64_audit_rules
      is defined and find_existing_media_export_64_audit_rules.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_media_export
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80722-2
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.7
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules mount 32-bit  oval:ssg-test_audit_rules_media_export_mount_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_media_export_mount_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-a\s+always,exit\s+(\-F\s+arch=b32\s+)(?:.*(-S[\s]+mount[\s]+|([\s]+|[,])mount([\s]+|[,])))(?:.*-F\s+auid>=1000\s+\-F\s+auid!=(?:4294967295|unset)\s+)(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules mount 64-bit  oval:ssg-test_64bit_ardm_media_export_mount_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_media_export_mount_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-a\s+always,exit\s+(\-F\s+arch=b64\s+)(?:.*(-S[\s]+mount[\s]+|([\s]+|[,])mount([\s]+|[,])))(?:.*-F\s+auid>=1000\s+\-F\s+auid!=(?:4294967295|unset)\s+)(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl mount 32-bit  oval:ssg-test_audit_rules_media_export_mount_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_media_export_mount_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-a\s+always,exit\s+(\-F\s+arch=b32\s+)(?:.*(-S[\s]+mount[\s]+|([\s]+|[,])mount([\s]+|[,])))(?:.*-F\s+auid>=1000\s+\-F\s+auid!=(?:4294967295|unset)\s+)(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl mount 64-bit  oval:ssg-test_64bit_ardm_media_export_mount_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_media_export_mount_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-a\s+always,exit\s+(\-F\s+arch=b64\s+)(?:.*(-S[\s]+mount[\s]+|([\s]+|[,])mount([\s]+|[,])))(?:.*-F\s+auid>=1000\s+\-F\s+auid!=(?:4294967295|unset)\s+)(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1
Record Events that Modify User/Group Information - /etc/gshadowxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_gshadow mediumCCE-80759-4

Record Events that Modify User/Group Information - /etc/gshadow

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_gshadow
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_usergroup_modification_gshadow:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80759-4

References:  5.2.5, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000018, CCI-000172, CCI-001403, CCI-001404, CCI-001405, CCI-001683, CCI-001684, CCI-001685, CCI-001686, CCI-002130, CCI-002132, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.5, SRG-OS-000004-GPOS-00004, SRG-OS-000004-VMM-000040, SRG-OS-000239-VMM-000810, SRG-OS-000240-VMM-000820, SRG-OS-000241-VMM-000830, SRG-OS-000274-VMM-000960, SRG-OS-000275-VMM-000970, SRG-OS-000276-VMM-000980, SRG-OS-000277-VMM-000990, SRG-OS-000303-VMM-001090, SRG-OS-000304-VMM-001100, SRG-OS-000476-VMM-001960

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, in order to capture events that modify account changes:

-w /etc/gshadow -p wa -k audit_rules_usergroup_modification


If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, in order to capture events that modify account changes:

-w /etc/gshadow -p wa -k audit_rules_usergroup_modification

Rationale

In addition to auditing new user and group accounts, these watches will alert the system administrator(s) to any modifications. Any unexpected users, groups, or modifications should be investigated for legitimacy.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/gshadow" "wa" "audit_rules_usergroup_modification"
fix_audit_watch_rule "augenrules" "/etc/gshadow" "wa" "audit_rules_usergroup_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit gshadow tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other user/group modification audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -k audit_rules_usergroup_modification$
    patterns: '*.rules'
  register: find_gshadow
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: If existing user/group modification ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_gshadow.matched is defined and find_gshadow.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_gshadow.files | map(attribute=''path'') | list | first }}'
  when:
    - find_gshadow.matched is defined and find_gshadow.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the gshadow rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the gshadow rule in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_gshadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80759-4
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules gshadow  oval:ssg-test_audit_rules_usergroup_modification_gshadow_augen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_gshadow_augen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+\/etc\/gshadow[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit gshadow  oval:ssg-test_audit_rules_usergroup_modification_gshadow_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_gshadow_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+\/etc\/gshadow[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1
Record Events that Modify the System's Network Environmentxccdf_org.ssgproject.content_rule_audit_rules_networkconfig_modification mediumCCE-80723-0

Record Events that Modify the System's Network Environment

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_networkconfig_modification
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_networkconfig_modification:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80723-0

References:  4.18, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.5.5

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, setting ARCH to either b32 or b64 as appropriate for your system:

-a always,exit -F arch=ARCH -S sethostname,setdomainname -F key=audit_rules_networkconfig_modification
-w /etc/issue -p wa -k audit_rules_networkconfig_modification
-w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
-w /etc/hosts -p wa -k audit_rules_networkconfig_modification
-w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S sethostname,setdomainname -F key=audit_rules_networkconfig_modification
-w /etc/issue -p wa -k audit_rules_networkconfig_modification
-w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
-w /etc/hosts -p wa -k audit_rules_networkconfig_modification
-w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification

Rationale

The network environment should not be modified by anything other than administrator action. Any change to network parameters should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
	PATTERN="-a always,exit -F arch=$ARCH -S .* -k *"
	# Use escaped BRE regex to specify rule group
	GROUP="set\(host\|domain\)name"
	FULL_RULE="-a always,exit -F arch=$ARCH -S sethostname -S setdomainname -k audit_rules_networkconfig_modification"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
	fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
	fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

# Then perform the remediations for the watch rules
# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/issue" "wa" "audit_rules_networkconfig_modification"
fix_audit_watch_rule "augenrules" "/etc/issue" "wa" "audit_rules_networkconfig_modification"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/issue.net" "wa" "audit_rules_networkconfig_modification"
fix_audit_watch_rule "augenrules" "/etc/issue.net" "wa" "audit_rules_networkconfig_modification"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/hosts" "wa" "audit_rules_networkconfig_modification"
fix_audit_watch_rule "augenrules" "/etc/hosts" "wa" "audit_rules_networkconfig_modification"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/sysconfig/network" "wa" "audit_rules_networkconfig_modification"
fix_audit_watch_rule "augenrules" "/etc/sysconfig/network" "wa" "audit_rules_networkconfig_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Remediate audit rules for network configuration for x86
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - sethostname
          - setdomainname

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_rules_networkconfig_modification
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as
        the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_rules_networkconfig_modification'
            }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - sethostname
          - setdomainname

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_rules_networkconfig_modification'
            }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Remediate audit rules for network configuration for x86_64
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - sethostname
          - setdomainname

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_rules_networkconfig_modification
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as
        the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_rules_networkconfig_modification'
            }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - sethostname
          - setdomainname

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_rules_networkconfig_modification'
            }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - audit_arch == "b64"
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/issue already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/issue\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key audit_rules_networkconfig_modification
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as the
    recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/issue in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/issue -p wa -k audit_rules_networkconfig_modification
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/issue already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/issue\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/issue in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/issue -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/issue.net already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/issue.net\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key audit_rules_networkconfig_modification
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as the
    recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/issue.net in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/issue.net already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/issue.net\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/issue.net in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/hosts already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/hosts\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key audit_rules_networkconfig_modification
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as the
    recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/hosts in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/hosts -p wa -k audit_rules_networkconfig_modification
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/hosts already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/hosts\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/hosts in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/hosts -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/sysconfig/network already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/sysconfig/network\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key audit_rules_networkconfig_modification
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules as the
    recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/sysconfig/network in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/sysconfig/network already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/sysconfig/network\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/sysconfig/network in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_networkconfig_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80723-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit /etc/issue augenrules  oval:ssg-test_arnm_etc_issue_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_issue_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/issue[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/issue.net augenrules  oval:ssg-test_arnm_etc_issue_net_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_issue_net_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/issue\.net[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/hosts augenrules  oval:ssg-test_arnm_etc_hosts_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_hosts_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/hosts[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/sysconfig/network augenrules  oval:ssg-test_arnm_etc_sysconfig_network_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_sysconfig_network_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/sysconfig/network[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit sethostname  oval:ssg-test_32bit_ardm_sethostname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_sethostname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit sethostname  oval:ssg-test_64bit_ardm_sethostname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_sethostname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit sethostname  oval:ssg-test_32bit_ardm_sethostname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_sethostname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit sethostname  oval:ssg-test_64bit_ardm_sethostname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_sethostname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit setdomainname  oval:ssg-test_32bit_ardm_setdomainname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setdomainname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit setdomainname  oval:ssg-test_64bit_ardm_setdomainname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setdomainname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit setdomainname  oval:ssg-test_32bit_ardm_setdomainname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setdomainname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit setdomainname  oval:ssg-test_64bit_ardm_setdomainname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setdomainname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit /etc/issue auditctl  oval:ssg-test_arnm_etc_issue_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_issue_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/issue[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/issue.net auditctl  oval:ssg-test_arnm_etc_issue_net_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_issue_net_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/issue\.net[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/hosts auditctl  oval:ssg-test_arnm_etc_hosts_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_hosts_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/hosts[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit /etc/sysconfig/network auditctl  oval:ssg-test_arnm_etc_sysconfig_network_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arnm_etc_sysconfig_network_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/sysconfig/network[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit sethostname  oval:ssg-test_32bit_ardm_sethostname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_sethostname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit sethostname  oval:ssg-test_64bit_ardm_sethostname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_sethostname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit sethostname  oval:ssg-test_32bit_ardm_sethostname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_sethostname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit sethostname  oval:ssg-test_64bit_ardm_sethostname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_sethostname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+sethostname[\s]+|([\s]+|[,])sethostname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules 32-bit setdomainname  oval:ssg-test_32bit_ardm_setdomainname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setdomainname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit augenrules 64-bit setdomainname  oval:ssg-test_64bit_ardm_setdomainname_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setdomainname_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl 32-bit setdomainname  oval:ssg-test_32bit_ardm_setdomainname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_32bit_ardm_setdomainname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1

64 bit architecture  oval:ssg-test_system_info_architecture_x86_64:tst:1  true

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppc_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_ppcle_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

64 bit architecture  oval:ssg-test_system_info_architecture_aarch_64:tst:1  false

Following items have been found on the system:
Machine classNode nameOs nameOs releaseOs versionProcessor type
x86_64rhel8.example.comLinux4.18.0-240.15.1.el8_3.x86_64#1 SMP Wed Feb 3 03:12:15 EST 2021x86_64

audit auditctl 64-bit setdomainname  oval:ssg-test_64bit_ardm_setdomainname_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_64bit_ardm_setdomainname_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+setdomainname[\s]+|([\s]+|[,])setdomainname([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$1
System Audit Logs Must Be Owned By Rootxccdf_org.ssgproject.content_rule_file_ownership_var_log_audit mediumCCE-80808-9

System Audit Logs Must Be Owned By Root

Rule IDxccdf_org.ssgproject.content_rule_file_ownership_var_log_audit
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_ownership_var_log_audit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80808-9

References:  1, 11, 12, 13, 14, 15, 16, 18, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO01.06, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, DSS06.02, MEA02.01, 3.3.1, CCI-000162, CCI-000163, CCI-000164, CCI-001314, 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 6.1, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), AU-9(4), DE.AE-3, DE.AE-5, PR.AC-4, PR.DS-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.5.1, SRG-OS-000057-GPOS-00027, SRG-OS-000058-GPOS-00028, SRG-OS-000059-GPOS-00029, SRG-OS-000206-GPOS-00084

Description

All audit logs must be owned by root user and group. By default, the path for audit log is

/var/log/audit/
. To properly set the owner of /var/log/audit, run the command:
$ sudo chown root /var/log/audit 
To properly set the owner of /var/log/audit/*, run the command:
$ sudo chown root /var/log/audit/* 

Rationale

Unauthorized disclosure of audit records can reveal system and configuration data to attackers, thus compromising its confidentiality.

OVAL test results details

/var/log/audit files uid root gid root  oval:ssg-test_ownership_var_log_audit_files:tst:1  true

No items have been found conforming to the following objects:
Object oval:ssg-object_ownership_var_log_audit_files:obj:1 of type file_object
BehaviorsPathFilenameFilter
no value/var/log/audit^.*$oval:ssg-state_owner_not_root_root_var_log_audit:ste:1

/var/log/audit directories uid root gid root  oval:ssg-test_ownership_var_log_audit_directories:tst:1  true

No items have been found conforming to the following objects:
Object oval:ssg-object_ownership_var_log_audit_directories:obj:1 of type file_object
BehaviorsPathFilenameFilter
no value/var/log/auditno valueoval:ssg-state_owner_not_root_root_var_log_audit:ste:1

log_group = root  oval:ssg-test_auditd_conf_log_group_not_root:tst:1  false

Following items have been found on the system:
PathContent
/etc/audit/auditd.conflog_group = root

/var/log/audit files uid root gid root  oval:ssg-test_ownership_var_log_audit_files-non_root:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/var/log/audit/audit.logregular002118771rw------- 

/var/log/audit directories uid root gid root  oval:ssg-test_ownership_var_log_audit_directories-non_root:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/var/log/audit/directory0023rwx------ 
Record Events that Modify the System's Mandatory Access Controlsxccdf_org.ssgproject.content_rule_audit_rules_mac_modification mediumCCE-80721-4

Record Events that Modify the System's Mandatory Access Controls

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_mac_modification
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_mac_modification:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80721-4

References:  4.1.7, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.8, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.5

Description

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:

-w /etc/selinux/ -p wa -k MAC-policy
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:
-w /etc/selinux/ -p wa -k MAC-policy

Rationale

The system's mandatory access policy (SELinux) should not be arbitrarily changed by anything other than administrator action. All changes to MAC policy should be audited.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/selinux/" "wa" "MAC-policy"
fix_audit_watch_rule "augenrules" "/etc/selinux/" "wa" "MAC-policy"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Check if watch rule for /etc/selinux/ already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/selinux/\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key MAC-policy
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)MAC-policy$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/MAC-policy.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/MAC-policy.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/selinux/ in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/selinux/ -p wa -k MAC-policy
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Check if watch rule for /etc/selinux/ already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/selinux/\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1

- name: Add watch rule for /etc/selinux/ in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/selinux/ -p wa -k MAC-policy
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_mac_modification
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80721-4
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.8
    - PCI-DSS-Req-10.5.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit selinux changes augenrules  oval:ssg-test_armm_selinux_watch_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_armm_selinux_watch_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/selinux/[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit selinux changes auditctl  oval:ssg-test_armm_selinux_watch_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_armm_selinux_watch_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/selinux/[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1
Record Events that Modify User/Group Information - /etc/shadowxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_shadow mediumCCE-80762-8

Record Events that Modify User/Group Information - /etc/shadow

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_shadow
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_usergroup_modification_shadow:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80762-8

References:  5.2.5, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000018, CCI-000172, CCI-001403, CCI-001404, CCI-001405, CCI-001683, CCI-001684, CCI-001685, CCI-001686, CCI-002130, CCI-002132, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.5, SRG-OS-000004-GPOS-00004, SRG-OS-000004-VMM-000040, SRG-OS-000239-VMM-000810, SRG-OS-000240-VMM-000820, SRG-OS-000241-VMM-000830, SRG-OS-000274-VMM-000960, SRG-OS-000275-VMM-000970, SRG-OS-000276-VMM-000980, SRG-OS-000277-VMM-000990, SRG-OS-000303-VMM-001090, SRG-OS-000304-VMM-001100, SRG-OS-000476-VMM-001960

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, in order to capture events that modify account changes:

-w /etc/shadow -p wa -k audit_rules_usergroup_modification


If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, in order to capture events that modify account changes:

-w /etc/shadow -p wa -k audit_rules_usergroup_modification

Rationale

In addition to auditing new user and group accounts, these watches will alert the system administrator(s) to any modifications. Any unexpected users, groups, or modifications should be investigated for legitimacy.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/shadow" "wa" "audit_rules_usergroup_modification"
fix_audit_watch_rule "augenrules" "/etc/shadow" "wa" "audit_rules_usergroup_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit shadow tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other user/group modification audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -k audit_rules_usergroup_modification$
    patterns: '*.rules'
  register: find_shadow
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: If existing user/group modification ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_shadow.matched is defined and find_shadow.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_shadow.files | map(attribute=''path'') | list | first }}'
  when:
    - find_shadow.matched is defined and find_shadow.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the shadow rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the shadow rule in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_shadow
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80762-8
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules shadow  oval:ssg-test_audit_rules_usergroup_modification_shadow_augen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_shadow_augen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+\/etc\/shadow[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit shadow  oval:ssg-test_audit_rules_usergroup_modification_shadow_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_shadow_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+\/etc\/shadow[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1
Record Events that Modify User/Group Information - /etc/passwdxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_passwd mediumCCE-80761-0

Record Events that Modify User/Group Information - /etc/passwd

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_passwd
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_usergroup_modification_passwd:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80761-0

References:  5.2.5, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000018, CCI-000172, CCI-001403, CCI-001404, CCI-001405, CCI-001683, CCI-001684, CCI-001685, CCI-001686, CCI-002130, CCI-002132, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.5, SRG-OS-000004-GPOS-00004, SRG-OS-000239-GPOS-00089, SRG-OS-000240-GPOS-00090, SRG-OS-000241-GPOS-00091, SRG-OS-000274-GPOS-00104, SRG-OS-000275-GPOS-00105, SRG-OS-000276-GPOS-00106, SRG-OS-000277-GPOS-00107, SRG-OS-000303-GPOS-00120, SRG-OS-000476-GPOS-00221, SRG-OS-000004-VMM-000040, SRG-OS-000239-VMM-000810, SRG-OS-000240-VMM-000820, SRG-OS-000241-VMM-000830, SRG-OS-000274-VMM-000960, SRG-OS-000275-VMM-000970, SRG-OS-000276-VMM-000980, SRG-OS-000277-VMM-000990, SRG-OS-000303-VMM-001090, SRG-OS-000304-VMM-001100, SRG-OS-000476-VMM-001960

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, in order to capture events that modify account changes:

-w /etc/passwd -p wa -k audit_rules_usergroup_modification


If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, in order to capture events that modify account changes:

-w /etc/passwd -p wa -k audit_rules_usergroup_modification

Rationale

In addition to auditing new user and group accounts, these watches will alert the system administrator(s) to any modifications. Any unexpected users, groups, or modifications should be investigated for legitimacy.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/passwd" "wa" "audit_rules_usergroup_modification"
fix_audit_watch_rule "augenrules" "/etc/passwd" "wa" "audit_rules_usergroup_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit passwd tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other user/group modification audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -k audit_rules_usergroup_modification$
    patterns: '*.rules'
  register: find_passwd
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: If existing user/group modification ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_passwd.matched is defined and find_passwd.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_passwd.files | map(attribute=''path'') | list | first }}'
  when:
    - find_passwd.matched is defined and find_passwd.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the passwd rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the passwd rule in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_passwd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80761-0
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules passwd  oval:ssg-test_audit_rules_usergroup_modification_passwd_augen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_passwd_augen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+\/etc\/passwd[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit passwd  oval:ssg-test_audit_rules_usergroup_modification_passwd_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_passwd_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+\/etc\/passwd[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1
Record Events that Modify User/Group Information - /etc/groupxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_group mediumCCE-80758-6

Record Events that Modify User/Group Information - /etc/group

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_group
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_usergroup_modification_group:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80758-6

References:  5.2.5, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000018, CCI-000172, CCI-001403, CCI-001404, CCI-001405, CCI-001683, CCI-001684, CCI-001685, CCI-001686, CCI-002130, CCI-002132, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.5, SRG-OS-000004-GPOS-00004, SRG-OS-000004-VMM-000040, SRG-OS-000239-VMM-000810, SRG-OS-000240-VMM-000820, SRG-OS-000241-VMM-000830, SRG-OS-000274-VMM-000960, SRG-OS-000275-VMM-000970, SRG-OS-000276-VMM-000980, SRG-OS-000277-VMM-000990, SRG-OS-000303-VMM-001090, SRG-OS-000304-VMM-001100, SRG-OS-000476-VMM-001960

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, in order to capture events that modify account changes:

-w /etc/group -p wa -k audit_rules_usergroup_modification


If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, in order to capture events that modify account changes:

-w /etc/group -p wa -k audit_rules_usergroup_modification

Rationale

In addition to auditing new user and group accounts, these watches will alert the system administrator(s) to any modifications. Any unexpected users, groups, or modifications should be investigated for legitimacy.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/group" "wa" "audit_rules_usergroup_modification"
fix_audit_watch_rule "augenrules" "/etc/group" "wa" "audit_rules_usergroup_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit group tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other user/group modification audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -k audit_rules_usergroup_modification$
    patterns: '*.rules'
  register: find_group
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: If existing user/group modification ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_group.matched is defined and find_group.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_group.files | map(attribute=''path'') | list | first }}'
  when:
    - find_group.matched is defined and find_group.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the group rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/group -p wa -k audit_rules_usergroup_modification
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the group rule in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/group -p wa -k audit_rules_usergroup_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_group
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80758-6
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules group  oval:ssg-test_audit_rules_usergroup_modification_group_augen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_group_augen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+\/etc\/group[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit group  oval:ssg-test_audit_rules_usergroup_modification_group_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_group_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+\/etc\/group[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1
Make the auditd Configuration Immutablexccdf_org.ssgproject.content_rule_audit_rules_immutable mediumCCE-80708-1

Make the auditd Configuration Immutable

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_immutable
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_immutable:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80708-1

References:  4.1.18, 1, 11, 12, 13, 14, 15, 16, 18, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO01.06, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, DSS06.02, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.3.1, 3.4.3, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.310(a)(2)(iv), 164.312(d), 164.310(d)(2)(iii), 164.312(b), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 6.1, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, ID.SC-4, PR.AC-4, PR.DS-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.5.2

Description

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



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

# 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

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Collect all files from /etc/audit/rules.d with .rules extension
  find:
    paths: /etc/audit/rules.d/
    patterns: '*.rules'
  register: find_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_immutable
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80708-1
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - PCI-DSS-Req-10.5.2
    - CJIS-5.4.1.1

- name: Remove the -e option from all Audit config files
  lineinfile:
    path: '{{ item }}'
    regexp: ^\s*(?:-e)\s+.*$
    state: absent
  loop: '{{ find_rules_d.files | map(attribute=''path'') | list + [''/etc/audit/audit.rules'']
    }}'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_immutable
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80708-1
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - PCI-DSS-Req-10.5.2
    - CJIS-5.4.1.1

- name: Add Audit -e option into /etc/audit/rules.d/immutable.rules and /etc/audit/audit.rules
  lineinfile:
    path: '{{ item }}'
    create: true
    line: -e 2
  loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_immutable
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80708-1
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - PCI-DSS-Req-10.5.2
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules configuration locked  oval:ssg-test_ari_locked_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_ari_locked_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-e\s+2\s*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl configuration locked  oval:ssg-test_ari_locked_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_ari_locked_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-e\s+2\s*$1
Record Attempts to Alter Process and Session Initiation Informationxccdf_org.ssgproject.content_rule_audit_rules_session_events mediumCCE-80742-0

Record Attempts to Alter Process and Session Initiation Information

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_session_events
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_session_events:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80742-0

References:  4.1.5, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AU-2(d), AU-12(c), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.3

Description

The audit system already collects process information for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d in order to watch for attempted manual edits of files involved in storing such process information:

-w /var/run/utmp -p wa -k session
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file in order to watch for attempted manual edits of files involved in storing such process information:
-w /var/run/utmp -p wa -k session
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session

Rationale

Manual editing of these files may indicate nefarious activity, such as an attacker attempting to remove evidence of an intrusion.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation
# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/var/run/utmp" "wa" "session"
fix_audit_watch_rule "augenrules" "/var/run/utmp" "wa" "session"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/var/log/btmp" "wa" "session"
fix_audit_watch_rule "augenrules" "/var/log/btmp" "wa" "session"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/var/log/wtmp" "wa" "session"
fix_audit_watch_rule "augenrules" "/var/log/wtmp" "wa" "session"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Check if watch rule for /var/run/utmp already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/var/run/utmp\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key session
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)session$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/session.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/session.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/run/utmp in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /var/run/utmp -p wa -k session
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Check if watch rule for /var/run/utmp already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/var/run/utmp\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/run/utmp in /etc/audit/audit.rules
  lineinfile:
    line: -w /var/run/utmp -p wa -k session
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Check if watch rule for /var/log/btmp already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/var/log/btmp\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key session
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)session$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/session.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/session.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/log/btmp in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /var/log/btmp -p wa -k session
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Check if watch rule for /var/log/btmp already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/var/log/btmp\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/log/btmp in /etc/audit/audit.rules
  lineinfile:
    line: -w /var/log/btmp -p wa -k session
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Check if watch rule for /var/log/wtmp already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/var/log/wtmp\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other rules with specified key session
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)session$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/session.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/session.rules
  when:
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/log/wtmp in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /var/log/wtmp -p wa -k session
    create: true
  when:
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Check if watch rule for /var/log/wtmp already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/var/log/wtmp\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1

- name: Add watch rule for /var/log/wtmp in /etc/audit/audit.rules
  lineinfile:
    line: -w /var/log/wtmp -p wa -k session
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when:
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_session_events
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80742-0
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.3
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules utmp  oval:ssg-test_arse_utmp_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_utmp_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w\s+/var/run/utmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit augenrules btmp  oval:ssg-test_arse_btmp_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_btmp_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w\s+/var/log/btmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit augenrules wtmp  oval:ssg-test_arse_wtmp_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_wtmp_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w\s+/var/log/wtmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl utmp  oval:ssg-test_arse_utmp_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_utmp_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w\s+/var/run/utmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit auditctl btmp  oval:ssg-test_arse_btmp_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_btmp_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w\s+/var/log/btmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1

audit auditctl wtmp  oval:ssg-test_arse_wtmp_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_arse_wtmp_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w\s+/var/log/wtmp\s+\-p\s+wa\s+(-k[\s]+|-F[\s]+key=)[-\w]+\s*$1
Record Events that Modify User/Group Information - /etc/security/opasswdxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_opasswd mediumCCE-80760-2

Record Events that Modify User/Group Information - /etc/security/opasswd

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification_opasswd
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_usergroup_modification_opasswd:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80760-2

References:  5.2.5, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000018, CCI-000172, CCI-001403, CCI-001404, CCI-001405, CCI-001683, CCI-001684, CCI-001685, CCI-001686, CCI-002130, CCI-002132, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.5, SRG-OS-000003-GPOS-00004, SRG-OS-000004-GPOS-00004, SRG-OS-000004-VMM-000040, SRG-OS-000239-VMM-000810, SRG-OS-000240-VMM-000820, SRG-OS-000241-VMM-000830, SRG-OS-000274-VMM-000960, SRG-OS-000275-VMM-000970, SRG-OS-000276-VMM-000980, SRG-OS-000277-VMM-000990, SRG-OS-000303-VMM-001090, SRG-OS-000304-VMM-001100, SRG-OS-000476-VMM-001960

Description

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, in order to capture events that modify account changes:

-w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification


If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, in order to capture events that modify account changes:

-w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification

Rationale

In addition to auditing new user and group accounts, these watches will alert the system administrator(s) to any modifications. Any unexpected users, groups, or modifications should be investigated for legitimacy.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/security/opasswd" "wa" "audit_rules_usergroup_modification"
fix_audit_watch_rule "augenrules" "/etc/security/opasswd" "wa" "audit_rules_usergroup_modification"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Set architecture for audit opasswd tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Search /etc/audit/rules.d for other user/group modification audit rules
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: -k audit_rules_usergroup_modification$
    patterns: '*.rules'
  register: find_opasswd
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: If existing user/group modification ruleset not found, use /etc/audit/rules.d/privileged.rules
    as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/privileged.rules
  when:
    - find_opasswd.matched is defined and find_opasswd.matched == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_opasswd.files | map(attribute=''path'') | list | first }}'
  when:
    - find_opasswd.matched is defined and find_opasswd.matched > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the opasswd rule in rules.d when on x86
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1

- name: Inserts/replaces the opasswd rule in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_usergroup_modification_opasswd
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - reboot_required
    - CCE-80760-2
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.5
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules opasswd  oval:ssg-test_audit_rules_usergroup_modification_opasswd_augen:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_opasswd_augen:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+\/etc\/security\/opasswd[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit opasswd  oval:ssg-test_audit_rules_usergroup_modification_opasswd_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_usergroup_modification_opasswd_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+\/etc\/security\/opasswd[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)\w+[\s]*$1
System Audit Logs Must Have Mode 0640 or Less Permissivexccdf_org.ssgproject.content_rule_file_permissions_var_log_audit mediumCCE-80819-6

System Audit Logs Must Have Mode 0640 or Less Permissive

Rule IDxccdf_org.ssgproject.content_rule_file_permissions_var_log_audit
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_permissions_var_log_audit:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80819-6

References:  1, 11, 12, 13, 14, 15, 16, 18, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO01.06, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, DSS06.02, MEA02.01, 3.3.1, CCI-000162, CCI-000163, CCI-000164, CCI-001314, 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 6.1, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), AU-9(4), DE.AE-3, DE.AE-5, PR.AC-4, PR.DS-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.5, SRG-OS-000057-GPOS-00027, SRG-OS-000058-GPOS-00028, SRG-OS-000059-GPOS-00029, SRG-OS-000206-GPOS-00084

Description

If log_group in /etc/audit/auditd.conf is set to a group other than the root group account, change the mode of the audit log files with the following command:

$ sudo chmod 0640 audit_file

Otherwise, change the mode of the audit log files with the following command:
$ sudo chmod 0600 audit_file

Rationale

If users can write to audit logs, audit trails can be modified or destroyed.

OVAL test results details

/var/log/audit files mode 0600  oval:ssg-test_file_permissions_var_log_audit:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_var_log_audit_files:obj:1 of type file_object
BehaviorsPathFilenameFilter
no value/var/log/audit^.*$oval:ssg-state_not_mode_0600:ste:1

log_group = root  oval:ssg-test_auditd_conf_log_group_not_root:tst:1  false

Following items have been found on the system:
PathContent
/etc/audit/auditd.conflog_group = root

/var/log/audit files mode 0640  oval:ssg-test_file_permissions_var_log_audit-non_root:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_var_log_audit_files-non_root:obj:1 of type file_object
BehaviorsPathFilenameFilter
no value/var/log/audit^.*$oval:ssg-state_not_mode_0640:ste:1
Ensure auditd Collects System Administrator Actionsxccdf_org.ssgproject.content_rule_audit_rules_sysadmin_actions mediumCCE-80743-8

Ensure auditd Collects System Administrator Actions

Rule IDxccdf_org.ssgproject.content_rule_audit_rules_sysadmin_actions
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-audit_rules_sysadmin_actions:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80743-8

References:  4.1.3, 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000130, CCI-000135, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.1, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.1.2, A.6.2.1, A.6.2.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, AC-2(7)(b), AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.2, Req-10.2.5.b, SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000462-VMM-001840, SRG-OS-000471-VMM-001910

Description

At a minimum, the audit system should collect administrator actions for all users and root. 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:

-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
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:
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions

Rationale

The actions taken by system administrators should be audited to keep a record of what was executed on the system, as well as, for accountability purposes.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then



# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/sudoers" "wa" "actions"
fix_audit_watch_rule "augenrules" "/etc/sudoers" "wa" "actions"
# Function to fix audit file system object watch rule for given path:
# * if rule exists, also verifies the -w bits match the requirements
# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
#   audit rules file, depending on the tool which was used to load audit rules
#
# Expects four arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules'
# * path                        	value of -w audit rule's argument
# * required access bits        	value of -p audit rule's argument
# * key                         	value of -k audit rule's argument
#
# Example call:
#
#       fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
#
function fix_audit_watch_rule {

# Load function arguments into local variables
local tool="$1"
local path="$2"
local required_access_bits="$3"
local key="$4"

# Check sanity of the input
if [ $# -ne "4" ]
then
	echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
#
# -----------------------------------------------------------------------------------------
# Tool used to load audit rules	| Rule already defined	|  Audit rules file to inspect	  |
# -----------------------------------------------------------------------------------------
#	auditctl		|     Doesn't matter	|  /etc/audit/audit.rules	  |
# -----------------------------------------------------------------------------------------
# 	augenrules		|          Yes		|  /etc/audit/rules.d/*.rules	  |
# 	augenrules		|          No		|  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
declare -a files_to_inspect
files_to_inspect=()

# Check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	exit 1
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules')
# If the audit is 'augenrules', then check if rule is already defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
elif [ "$tool" == 'augenrules' ]
then
	readarray -t matches < <(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)

	# For each of the matched entries
	for match in "${matches[@]}"
	do
		# Extract filepath from the match
		rulesd_audit_file=$(echo $match | cut -f1 -d ':')
		# Append that path into list of files for inspection
		files_to_inspect+=("$rulesd_audit_file")
	done
	# Case when particular audit rule isn't defined yet
	if [ "${#files_to_inspect[@]}" -eq "0" ]
	then
		# Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
		local key_rule_file="/etc/audit/rules.d/$key.rules"
		# If the $key.rules file doesn't exist yet, create it with correct permissions
		if [ ! -e "$key_rule_file" ]
		then
			touch "$key_rule_file"
			chmod 0640 "$key_rule_file"
		fi

		files_to_inspect+=("$key_rule_file")
	fi
fi

# Finally perform the inspection and possible subsequent audit rule
# correction for each of the files previously identified for inspection
for audit_rules_file in "${files_to_inspect[@]}"
do

	# Check if audit watch file system object rule for given path already present
	if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
	then
		# Rule is found => verify yet if existing rule definition contains
		# all of the required access type bits

		# Escape slashes in path for use in sed pattern below
		local esc_path=${path//$'/'/$'\/'}
		# Define BRE whitespace class shortcut
		local sp="[[:space:]]"
		# Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
		current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
		# Split required access bits string into characters array
		# (to check bit's presence for one bit at a time)
		for access_bit in $(echo "$required_access_bits" | grep -o .)
		do
			# For each from the required access bits (e.g. 'w', 'a') check
			# if they are already present in current access bits for rule.
			# If not, append that bit at the end
			if ! grep -q "$access_bit" <<< "$current_access_bits"
			then
				# Concatenate the existing mask with the missing bit
				current_access_bits="$current_access_bits$access_bit"
			fi
		done
		# Propagate the updated rule's access bits (original + the required
		# ones) back into the /etc/audit/audit.rules file for that rule
		sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
	else
		# Rule isn't present yet. Append it at the end of $audit_rules_file file
		# with proper key

		echo "-w $path -p $required_access_bits -k $key" >> "$audit_rules_file"
	fi
done
}
fix_audit_watch_rule "auditctl" "/etc/sudoers.d/" "wa" "actions"
fix_audit_watch_rule "augenrules" "/etc/sudoers.d/" "wa" "actions"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Search /etc/audit/rules.d for audit rule entries for sysadmin actions
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*/etc/sudoers.*$
    patterns: '*.rules'
  register: find_audit_sysadmin_actions
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Use /etc/audit/rules.d/actions.rules as the recipient for the rule
  set_fact:
    all_sysadmin_actions_files:
      - /etc/audit/rules.d/actions.rules
  when:
    - find_audit_sysadmin_actions.matched is defined and find_audit_sysadmin_actions.matched
      == 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Use matched file as the recipient for the rule
  set_fact:
    all_sysadmin_actions_files:
      - '{{ find_audit_sysadmin_actions.files | map(attribute=''path'') | list | first
        }}'
  when:
    - find_audit_sysadmin_actions.matched is defined and find_audit_sysadmin_actions.matched
      > 0
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Inserts/replaces audit rule for /etc/sudoers rule in rules.d
  lineinfile:
    path: '{{ all_sysadmin_actions_files[0] }}'
    line: -w /etc/sudoers -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Inserts/replaces audit rule for /etc/sudoers.d rule in rules.d
  lineinfile:
    path: '{{ all_sysadmin_actions_files[0] }}'
    line: -w /etc/sudoers.d/ -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Inserts/replaces audit rule for /etc/sudoers in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -w /etc/sudoers -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1

- name: Inserts/replaces audit rule for /etc/sudoers.d in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -w /etc/sudoers.d/ -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - audit_rules_sysadmin_actions
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80743-8
    - NIST-800-53-AC-2(7)(b)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.7
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - CJIS-5.4.1.1
OVAL test results details

audit augenrules  oval:ssg-test_audit_rules_augenrules:tst:1  true

Following items have been found on the system:
PathContent
/usr/lib/systemd/system/auditd.serviceExecStartPost=-/sbin/augenrules --load

audit augenrules sudoers  oval:ssg-test_audit_rules_sysadmin_actions_sudoers_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_sysadmin_actions_sudoers_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/sudoers[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit augenrules sudoers  oval:ssg-test_audit_rules_sysadmin_actions_sudoers_d_augenrules:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_sysadmin_actions_sudoers_d_augenrules:obj:1 of type textfilecontent54_object
FilepathPatternInstance
^/etc/audit/rules\.d/.*\.rules$^\-w[\s]+/etc/sudoers\.d/[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit auditctl  oval:ssg-test_audit_rules_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/usr/lib/systemd/system/auditd.service^ExecStartPost=\-\/sbin\/auditctl.*$1

audit auditctl sudoers  oval:ssg-test_audit_rules_sysadmin_actions_sudoers_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_sysadmin_actions_sudoers_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/sudoers[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1

audit auditctl sudoers  oval:ssg-test_audit_rules_sysadmin_actions_sudoers_d_auditctl:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_audit_rules_sysadmin_actions_sudoers_d_auditctl:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/audit.rules^\-w[\s]+/etc/sudoers\.d/[\s]+\-p[\s]+\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b[\s]+(-k[\s]+|-F[\s]+key=)[-\w]+[\s]*$1
Configure auditd to use audispd's syslog pluginxccdf_org.ssgproject.content_rule_auditd_audispd_syslog_plugin_activated mediumCCE-80677-8

Configure auditd to use audispd's syslog plugin

Rule IDxccdf_org.ssgproject.content_rule_auditd_audispd_syslog_plugin_activated
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_audispd_syslog_plugin_activated:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80677-8

References:  1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-000136, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(B), 164.308(a)(5)(ii)(C), 164.308(a)(6)(ii), 164.308(a)(8), 164.310(d)(2)(iii), 164.312(b), 164.314(a)(2)(i)(C), 164.314(a)(2)(iii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, AU-4(1), CM-6(a), DE.AE-3, DE.AE-5, PR.PT-1, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.5.3, SRG-OS-000479-GPOS-00224, SRG-OS-000342-GPOS-00133, SRG-OS-000051-VMM-000230, SRG-OS-000058-VMM-000270, SRG-OS-000059-VMM-000280, SRG-OS-000479-VMM-001990, SRG-OS-000479-VMM-001990

Description

To configure the auditd service to use the syslog plug-in of the audispd audit event multiplexor, set the active line in /etc/audit/plugins.d/syslog.conf to yes. Restart the auditd service:

$ sudo service auditd restart

Rationale

The auditd service does not include the ability to send audit records to a centralized server for management directly. It does, however, include a plug-in for audit event multiplexor (audispd) to pass audit records to the local syslog server



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_syslog_active="yes"


AUDISP_SYSLOGCONFIG=/etc/audit/plugins.d/syslog.conf
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append $AUDISP_SYSLOGCONFIG '^active' "$var_syslog_active" "CCE-80677-8"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: enable syslog plugin
  lineinfile:
    dest: /etc/audit/plugins.d/syslog.conf
    regexp: ^active
    line: active = yes
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - auditd_audispd_syslog_plugin_activated
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80677-8
    - NIST-800-53-AU-4(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.5.3
    - CJIS-5.4.1.1
OVAL test results details

audispd syslog plugin activated  oval:ssg-test_auditd_audispd_syslog_plugin_activated:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_auditd_audispd_syslog_plugin_activated:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/audit/plugins.d/syslog.conf^[ ]*active[ ]+=[ ]+yes[ ]*$1
Configure auditd space_left Action on Low Disk Spacexccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action mediumCCE-80684-4

Configure auditd space_left Action on Low Disk Space

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_space_left_action:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80684-4

References:  4.1.2.3, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7, SRG-OS-000343-GPOS-00134, SRG-OS-000343-VMM-001240

Description

The auditd service can be configured to take an action when disk space starts to run low. Edit the file /etc/audit/auditd.conf. Modify the following line, substituting ACTION appropriately:

space_left_action = ACTION
Possible values for ACTION are described in the auditd.conf man page. These include:
  • syslog
  • email
  • exec
  • suspend
  • single
  • halt
Set this to email (instead of the default, which is suspend) as it is more likely to get prompt attention. Acceptable values also include suspend, single, and halt.

Rationale

Notifying administrators of an impending disk space problem may allow them to take corrective action prior to any disruption.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_auditd_space_left_action="email"

#
# If space_left_action present in /etc/audit/auditd.conf, change value
# to var_auditd_space_left_action, else
# add "space_left_action = $var_auditd_space_left_action" to /etc/audit/auditd.conf
#

AUDITCONFIG=/etc/audit/auditd.conf
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append $AUDITCONFIG '^space_left_action' "$var_auditd_space_left_action" "CCE-80684-4"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_auditd_space_left_action # promote to variable
  set_fact:
    var_auditd_space_left_action: !!str email
  tags:
    - always

- name: Configure auditd space_left Action on Low Disk Space
  lineinfile:
    dest: /etc/audit/auditd.conf
    line: space_left_action = {{ var_auditd_space_left_action }}
    regexp: ^\s*space_left_action\s*=\s*.*$
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - auditd_data_retention_space_left_action
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80684-4
    - NIST-800-53-AU-5(b)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.7
    - CJIS-5.4.1.1
OVAL test results details

space left action  oval:ssg-test_auditd_data_retention_space_left_action:tst:1  false

Following items have been found on the system:
PathContent
/etc/audit/auditd.confspace_left_action = SYSLOG
Configure auditd mail_acct Action on Low Disk Spacexccdf_org.ssgproject.content_rule_auditd_data_retention_action_mail_acct mediumCCE-80678-6

Configure auditd mail_acct Action on Low Disk Space

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_action_mail_acct
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_action_mail_acct:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80678-6

References:  4.1.2.3, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-000139, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, IA-5(1), AU-5(a), AU-5(2), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7.a, SRG-OS-000343-GPOS-00134, SRG-OS-000046-VMM-000210, SRG-OS-000343-VMM-001240

Description

The auditd service can be configured to send email to a designated account in certain situations. Add or correct the following line in /etc/audit/auditd.conf to ensure that administrators are notified via email for those situations:

action_mail_acct = root

Rationale

Email sent to the root account is typically aliased to the administrators of the system, who can take appropriate action.

OVAL test results details

email account for actions  oval:ssg-test_auditd_data_retention_action_mail_acct:tst:1  true

Following items have been found on the system:
PathContent
/etc/audit/auditd.confaction_mail_acct = root
Configure auditd Max Log File Sizexccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file mediumCCE-80681-0

Configure auditd Max Log File Size

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_max_log_file:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80681-0

References:  4.1.2.1, 1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, AU-11, CM-6(a), DE.AE-3, DE.AE-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7

Description

Determine the amount of audit data (in megabytes) which should be retained in each log file. Edit the file /etc/audit/auditd.conf. Add or modify the following line, substituting the correct value of 6 for STOREMB:

max_log_file = STOREMB
Set the value to 6 (MB) or higher for general-purpose systems. Larger values, of course, support retention of even more audit data.

Rationale

The total storage for audit log files must be large enough to retain log information over the period required. This is a function of the maximum log file size and the number of logs retained.

OVAL test results details

max log file size  oval:ssg-test_auditd_data_retention_max_log_file:tst:1  true

Following items have been found on the system:
PathContent
/etc/audit/auditd.confmax_log_file = 8
Configure auditd admin_space_left Action on Low Disk Spacexccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action mediumCCE-80679-4

Configure auditd admin_space_left Action on Low Disk Space

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_admin_space_left_action:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80679-4

References:  4.1.2.3, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-000140, CCI-001343, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7, SRG-OS-000343-GPOS-00134

Description

The auditd service can be configured to take an action when disk space is running low but prior to running out of space completely. Edit the file /etc/audit/auditd.conf. Add or modify the following line, substituting ACTION appropriately:

admin_space_left_action = ACTION
Set this value to single to cause the system to switch to single user mode for corrective action. Acceptable values also include suspend and halt. For certain systems, the need for availability outweighs the need to log all actions, and a different setting should be determined. Details regarding all possible values for ACTION are described in the auditd.conf man page.

Rationale

Administrators should be made aware of an inability to record audit records. If a separate partition or logical volume of adequate size is used, running low on space for audit records should never occur.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_auditd_admin_space_left_action="single"

AUDITCONFIG=/etc/audit/auditd.conf
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append $AUDITCONFIG '^admin_space_left_action' "$var_auditd_admin_space_left_action" "CCE-80679-4"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_auditd_admin_space_left_action # promote to variable
  set_fact:
    var_auditd_admin_space_left_action: !!str single
  tags:
    - always

- name: Configure auditd admin_space_left Action on Low Disk Space
  lineinfile:
    dest: /etc/audit/auditd.conf
    line: admin_space_left_action = {{ var_auditd_admin_space_left_action }}
    regexp: ^\s*admin_space_left_action\s*=\s*.*$
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - auditd_data_retention_admin_space_left_action
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80679-4
    - NIST-800-53-AU-5(b)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.7
    - CJIS-5.4.1.1
OVAL test results details

space left action  oval:ssg-test_auditd_data_retention_admin_space_left_action:tst:1  false

Following items have been found on the system:
PathContent
/etc/audit/auditd.confadmin_space_left_action = SUSPEND
Configure auditd max_log_file_action Upon Reaching Maximum Log Sizexccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action mediumCCE-80682-8

Configure auditd max_log_file_action Upon Reaching Maximum Log Size

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_max_log_file_action:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80682-8

References:  4.1.2.2, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7

Description

The default action to take when the logs reach their maximum size is to rotate the log files, discarding the oldest one. To configure the action taken by auditd, add or correct the line in /etc/audit/auditd.conf:

max_log_file_action = ACTION
Possible values for ACTION are described in the auditd.conf man page. These include:
  • syslog
  • suspend
  • rotate
  • keep_logs
Set the ACTION to rotate to ensure log rotation occurs. This is the default. The setting is case-insensitive.

Rationale

Automatically rotating logs (by setting this to rotate) minimizes the chances of the system unexpectedly running out of disk space by being overwhelmed with log data. However, for systems that must never discard log data, or which use external processes to transfer it and reclaim space, keep_logs can be employed.

OVAL test results details

admin space left action   oval:ssg-test_auditd_data_retention_max_log_file_action:tst:1  true

Following items have been found on the system:
PathContent
/etc/audit/auditd.confmax_log_file_action = ROTATE
Configure auditd Number of Logs Retainedxccdf_org.ssgproject.content_rule_auditd_data_retention_num_logs mediumCCE-80683-6

Configure auditd Number of Logs Retained

Rule IDxccdf_org.ssgproject.content_rule_auditd_data_retention_num_logs
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-auditd_data_retention_num_logs:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80683-6

References:  1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, AU-11, CM-6(a), DE.AE-3, DE.AE-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7

Description

Determine how many log files auditd should retain when it rotates logs. Edit the file /etc/audit/auditd.conf. Add or modify the following line, substituting NUMLOGS with the correct value of 5:

num_logs = NUMLOGS
Set the value to 5 for general-purpose systems. Note that values less than 2 result in no log rotation.

Rationale

The total storage for audit log files must be large enough to retain log information over the period required. This is a function of the maximum log file size and the number of logs retained.

OVAL test results details

admin space left action   oval:ssg-test_auditd_data_retention_num_logs:tst:1  true

Following items have been found on the system:
PathContent
/etc/audit/auditd.confnum_logs = 5
Install audispd-plugins Packagexccdf_org.ssgproject.content_rule_package_audispd-plugins_installed mediumCCE-82953-1

Install audispd-plugins Package

Rule IDxccdf_org.ssgproject.content_rule_package_audispd-plugins_installed
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-package_audispd-plugins_installed:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-82953-1

References:  SRG-OS-000342-GPOS-00133

Description

The audispd-plugins package can be installed with the following command:

$ sudo yum install audispd-plugins

Rationale

audispd-plugins provides plugins for the real-time interface to the audit subsystem, audispd. These plugins can do things like relay events to remote machines or analyze events for suspicious behavior.



Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "audispd-plugins" ; then
    yum install -y "audispd-plugins"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:enable
- name: Ensure audispd-plugins is installed
  package:
    name: audispd-plugins
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - package_audispd-plugins_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-82953-1


Complexity:low
Disruption:low
Strategy:enable
include install_audispd-plugins

class install_audispd-plugins {
  package { 'audispd-plugins':
    ensure => 'installed',
  }
}


Complexity:low
Disruption:low
Strategy:enable

package --add=audispd-plugins
OVAL test results details

package audispd-plugins is installed  oval:ssg-test_package_audispd-plugins_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_audispd-plugins_installed:obj:1 of type rpminfo_object
Name
audispd-plugins
Enable auditd Servicexccdf_org.ssgproject.content_rule_service_auditd_enabled highCCE-80872-5

Enable auditd Service

Rule IDxccdf_org.ssgproject.content_rule_service_auditd_enabled
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-service_auditd_enabled:def:1
Time2021-03-21T20:15:13+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80872-5

References:  4.1.1.2, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.3.1, 3.3.2, 3.3.6, CCI-000126, CCI-000130, CCI-000131, CCI-000132, CCI-000133, CCI-000134, CCI-000135, CCI-001464, CCI-001487, CCI-001814, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AC-2(g), AU-3, AU-10, AU-2(d), AU-12(c), AU-14(1), AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.1, SRG-OS-000037-GPOS-00015, SRG-OS-000038-GPOS-00016, SRG-OS-000039-GPOS-00017, SRG-OS-000040-GPOS-00018, SRG-OS-000042-GPOS-00021, SRG-OS-000254-GPOS-00095, SRG-OS-000255-GPOS-00096, SRG-OS-000365-GPOS-00152, SRG-OS-000037-VMM-000150, SRG-OS-000063-VMM-000310, SRG-OS-000038-VMM-000160, SRG-OS-000039-VMM-000170, SRG-OS-000040-VMM-000180, SRG-OS-000041-VMM-000190

Description

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.

OVAL test results details

package audit is installed  oval:ssg-test_service_auditd_package_audit_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
auditx86_64(none)0.17.20191104git1c2f876.el83.00:3.0-0.17.20191104git1c2f876.el8199e2f91fd431d51audit-0:3.0-0.17.20191104git1c2f876.el8.x86_64

Test that the auditd service is running  oval:ssg-test_service_running_auditd:tst:1  true

Following items have been found on the system:
UnitPropertyValue
auditd.serviceActiveStateactive

systemd test  oval:ssg-test_multi_user_wants_auditd:tst:1  true

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_auditd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service
Enable Auditing for Processes Which Start Prior to the Audit Daemonxccdf_org.ssgproject.content_rule_grub2_audit_argument mediumCCE-80825-3

Enable Auditing for Processes Which Start Prior to the Audit Daemon

Rule IDxccdf_org.ssgproject.content_rule_grub2_audit_argument
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-grub2_audit_argument:def:1
Time2021-03-21T20:15:13+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80825-3

References:  4.1.1.3, 1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.02, DSS05.03, DSS05.04, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.3.1, CCI-001464, CCI-000130, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 7.1, SR 7.6, A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2, AC-17(1), AU-14(1), AU-10, CM-6(a), IR-5(1), DE.AE-3, DE.AE-5, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.3, SRG-OS-000254-GPOS-00095, SRG-OS-000254-VMM-000880

Description

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 /boot/grub2/grubenv, in the manner below:

# grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) audit=1"

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.

Warnings
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


# Remediation is applicable only in certain platforms
if rpm --quiet -q grub2-common && [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

# Correct grub2 kernelopts value using grub2-editenv
if ! grub2-editenv - list | grep -qE '^kernelopts=(.*\s)?audit=1(\s.*)?$'; then
  grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) audit=1"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:medium
Disruption:low
Reboot:true
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - grub2_audit_argument
    - medium_severity
    - restrict_strategy
    - medium_complexity
    - low_disruption
    - reboot_required
    - CCE-80825-3
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-AU-10
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.3
    - CJIS-5.4.1.1

- name: get current kernel parameters
  command: /usr/bin/grub2-editenv - list
  register: kernelopts
  changed_when: false
  when:
    - '"grub2-common" in ansible_facts.packages'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - grub2_audit_argument
    - medium_severity
    - restrict_strategy
    - medium_complexity
    - low_disruption
    - reboot_required
    - CCE-80825-3
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-AU-10
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.3
    - CJIS-5.4.1.1

- name: Update the bootloader menu
  command: /usr/bin/grub2-editenv - set "{{ item }} audit=1"
  with_items: '{{ kernelopts.stdout_lines | select(''match'', ''^kernelopts.*'') |
    list }}'
  when:
    - kernelopts.stdout_lines is defined
    - kernelopts.stdout_lines | length > 0
    - kernelopts.stdout | regex_search('^kernelopts=(?:.*\s)?audit=1(?:\s.*)?$', multiline=True)
      is none
    - '"grub2-common" in ansible_facts.packages'
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - grub2_audit_argument
    - medium_severity
    - restrict_strategy
    - medium_complexity
    - low_disruption
    - reboot_required
    - CCE-80825-3
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-AU-10
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - NIST-800-171-3.3.1
    - PCI-DSS-Req-10.3
    - CJIS-5.4.1.1


apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
spec:
  kernelArguments:
    - audit=1
OVAL test results details

check forkernel command line parameters audit=1 in /boot/grub2/grubenv for all kernels  oval:ssg-test_grub2_audit_argument_grub_env:tst:1  false

Following items have been found on the system:
PathContent
/boot/grub2/grubenvkernelopts=root=/dev/mapper/rhel-root ro crashkernel=auto resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet
Ensure gpgcheck Enabled In Main yum Configurationxccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated highCCE-80790-9

Ensure gpgcheck Enabled In Main yum Configuration

Rule IDxccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-ensure_gpgcheck_globally_activated:def:1
Time2021-03-21T20:15:22+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80790-9

References:  NT28(R15), 1.2.4, 11, 2, 3, 9, 5.10.4.1, APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02, 3.4.8, CCI-001749, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), SA-12, SA-12(10), CM-11(a), CM-11(b), PR.DS-6, PR.DS-8, PR.IP-1, FAU_GEN.1.1.c, Req-6.2, SRG-OS-000366-GPOS-00153, SRG-OS-000366-VMM-001430, SRG-OS-000370-VMM-001460, SRG-OS-000404-VMM-001650

Description

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

OVAL test results details

check value of gpgcheck in /etc/yum.conf  oval:ssg-test_ensure_gpgcheck_globally_activated:tst:1  true

Following items have been found on the system:
PathContent
/etc/yum.confgpgcheck=1
Ensure Red Hat GPG Key Installedxccdf_org.ssgproject.content_rule_ensure_redhat_gpgkey_installed highCCE-80795-8

Ensure Red Hat GPG Key Installed

Rule IDxccdf_org.ssgproject.content_rule_ensure_redhat_gpgkey_installed
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-ensure_redhat_gpgkey_installed:def:1
Time2021-03-21T20:15:22+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80795-8

References:  NT28(R15), 1.2.3, 11, 2, 3, 9, 5.10.4.1, APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02, 3.4.8, CCI-001749, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), PR.DS-6, PR.DS-8, PR.IP-1, FAU_GEN.1.1.c, Req-6.2, SRG-OS-000366-GPOS-00153, SRG-OS-000366-VMM-001430, SRG-OS-000370-VMM-001460, SRG-OS-000404-VMM-001650

Description

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
Alternatively, the key may be pre-loaded during the RHEL installation. In such cases, the key can be installed by running the following command:
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

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.

OVAL test results details

installed OS part of unix family  oval:ssg-test_rhel8_unix_family:tst:1  true

Following items have been found on the system:
Family
unix

installed OS part of unix family  oval:ssg-test_rhel8_unix_family:tst:1  true

Following items have been found on the system:
Family
unix

redhat-release is version 8  oval:ssg-test_rhel8:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
redhat-releasex86_64(none)1.0.el88.30:8.3-1.0.el8199e2f91fd431d51redhat-release-0:8.3-1.0.el8.x86_64

redhat-release is version 8  oval:ssg-test_rhel8:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
redhat-releasex86_64(none)1.0.el88.30:8.3-1.0.el8199e2f91fd431d51redhat-release-0:8.3-1.0.el8.x86_64

redhat-release-coreos is version 8  oval:ssg-test_rhel8_coreos:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhel8_coreos:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/os-release^PRETTY_NAME="Red Hat Enterprise Linux CoreOS \d+\.(\d)\d+\.[\d\.\-]+ \([\w\s]+\)"$1

redhat-release-coreos is version 8  oval:ssg-test_rhel8_coreos:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhel8_coreos:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/os-release^PRETTY_NAME="Red Hat Enterprise Linux CoreOS \d+\.(\d)\d+\.[\d\.\-]+ \([\w\s]+\)"$1

redhat-release-virtualization-host RPM package is installed  oval:ssg-test_rhvh4_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhvh4_version:obj:1 of type rpminfo_object
Name
redhat-release-virtualization-host

redhat-release-virtualization-host RPM package is installed  oval:ssg-test_rhvh4_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhvh4_version:obj:1 of type rpminfo_object
Name
redhat-release-virtualization-host

RHEVH base RHEL is version 8  oval:ssg-test_rhevh_rhel8_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhevh_rhel8_version:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/redhat-release^Red Hat Enterprise Linux release (\d)\.\d+$1

RHEVH base RHEL is version 8  oval:ssg-test_rhevh_rhel8_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhevh_rhel8_version:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/redhat-release^Red Hat Enterprise Linux release (\d)\.\d+$1

installed OS part of unix family  oval:ssg-test_rhel8_unix_family:tst:1  true

Following items have been found on the system:
Family
unix

installed OS part of unix family  oval:ssg-test_rhel8_unix_family:tst:1  true

Following items have been found on the system:
Family
unix

redhat-release is version 8  oval:ssg-test_rhel8:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
redhat-releasex86_64(none)1.0.el88.30:8.3-1.0.el8199e2f91fd431d51redhat-release-0:8.3-1.0.el8.x86_64

redhat-release is version 8  oval:ssg-test_rhel8:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
redhat-releasex86_64(none)1.0.el88.30:8.3-1.0.el8199e2f91fd431d51redhat-release-0:8.3-1.0.el8.x86_64

redhat-release-coreos is version 8  oval:ssg-test_rhel8_coreos:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhel8_coreos:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/os-release^PRETTY_NAME="Red Hat Enterprise Linux CoreOS \d+\.(\d)\d+\.[\d\.\-]+ \([\w\s]+\)"$1

redhat-release-coreos is version 8  oval:ssg-test_rhel8_coreos:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhel8_coreos:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/os-release^PRETTY_NAME="Red Hat Enterprise Linux CoreOS \d+\.(\d)\d+\.[\d\.\-]+ \([\w\s]+\)"$1

redhat-release-virtualization-host RPM package is installed  oval:ssg-test_rhvh4_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhvh4_version:obj:1 of type rpminfo_object
Name
redhat-release-virtualization-host

redhat-release-virtualization-host RPM package is installed  oval:ssg-test_rhvh4_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhvh4_version:obj:1 of type rpminfo_object
Name
redhat-release-virtualization-host

RHEVH base RHEL is version 8  oval:ssg-test_rhevh_rhel8_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhevh_rhel8_version:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/redhat-release^Red Hat Enterprise Linux release (\d)\.\d+$1

RHEVH base RHEL is version 8  oval:ssg-test_rhevh_rhel8_version:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_rhevh_rhel8_version:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/redhat-release^Red Hat Enterprise Linux release (\d)\.\d+$1

Red Hat release key package is installed  oval:ssg-test_package_gpgkey-fd431d51-4ae0493b_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
gpg-pubkey(none)(none)59d6ac66bf6a70410:bf6a7041-59d6ac660gpg-pubkey-0:bf6a7041-59d6ac66.(none)
gpg-pubkey(none)(none)56c6038f038651bd0:038651bd-56c6038f0gpg-pubkey-0:038651bd-56c6038f.(none)
gpg-pubkey(none)(none)52d46e88d59097ab0:d59097ab-52d46e880gpg-pubkey-0:d59097ab-52d46e88.(none)
gpg-pubkey(none)(none)4ae0493bfd431d510:fd431d51-4ae0493b0gpg-pubkey-0:fd431d51-4ae0493b.(none)
gpg-pubkey(none)(none)5b32db75d40827920:d4082792-5b32db750gpg-pubkey-0:d4082792-5b32db75.(none)
gpg-pubkey(none)(none)5cf7cefb2f86d6a10:2f86d6a1-5cf7cefb0gpg-pubkey-0:2f86d6a1-5cf7cefb.(none)
gpg-pubkey(none)(none)5d36ccdc8e6c95780:8e6c9578-5d36ccdc0gpg-pubkey-0:8e6c9578-5d36ccdc.(none)

Red Hat auxiliary key package is installed  oval:ssg-test_package_gpgkey-d4082792-5b32db75_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
gpg-pubkey(none)(none)59d6ac66bf6a70410:bf6a7041-59d6ac660gpg-pubkey-0:bf6a7041-59d6ac66.(none)
gpg-pubkey(none)(none)56c6038f038651bd0:038651bd-56c6038f0gpg-pubkey-0:038651bd-56c6038f.(none)
gpg-pubkey(none)(none)52d46e88d59097ab0:d59097ab-52d46e880gpg-pubkey-0:d59097ab-52d46e88.(none)
gpg-pubkey(none)(none)4ae0493bfd431d510:fd431d51-4ae0493b0gpg-pubkey-0:fd431d51-4ae0493b.(none)
gpg-pubkey(none)(none)5b32db75d40827920:d4082792-5b32db750gpg-pubkey-0:d4082792-5b32db75.(none)
gpg-pubkey(none)(none)5cf7cefb2f86d6a10:2f86d6a1-5cf7cefb0gpg-pubkey-0:2f86d6a1-5cf7cefb.(none)
gpg-pubkey(none)(none)5d36ccdc8e6c95780:8e6c9578-5d36ccdc0gpg-pubkey-0:8e6c9578-5d36ccdc.(none)
Ensure Software Patches Installedxccdf_org.ssgproject.content_rule_security_patches_up_to_date highCCE-80865-9

Ensure Software Patches Installed

Rule IDxccdf_org.ssgproject.content_rule_security_patches_up_to_date
Result
notchecked
Multi-check ruleyes
OVAL Definition ID
Time2021-03-21T20:15:22+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80865-9

References:  NT28(R08), 1.9, 18, 20, 4, 5.10.4.1, APO12.01, APO12.02, APO12.03, APO12.04, BAI03.10, DSS05.01, DSS05.02, CCI-000366, 4.2.3, 4.2.3.12, 4.2.3.7, 4.2.3.9, A.12.6.1, A.14.2.3, A.16.1.3, A.18.2.2, A.18.2.3, SI-2(5), SI-2(c), CM-6(a), ID.RA-1, PR.IP-12, FMT_MOF_EXT.1, Req-6.2, SRG-OS-000480-GPOS-00227, SRG-OS-000480-VMM-002000

Description

If the system is joined to the Red Hat Network, a Red Hat Satellite Server, or a yum server, run the following command to install updates:

$ sudo yum update
If the system is not configured to use one of these sources, updates (in the form of RPM packages) can be manually downloaded from the Red Hat Network and installed using rpm.

NOTE: U.S. Defense systems are required to be patched within 30 days or sooner as local policy dictates.

Rationale

Installing software updates is a fundamental mitigation against the exploitation of publicly-known vulnerabilities. If the most recent security patches and updates are not installed, unauthorized users may take advantage of weaknesses in the unpatched software. The lack of prompt attention to patching could result in a system compromise.

Evaluation messages
info 
None of the check-content-ref elements was resolvable.
Ensure gpgcheck Enabled for All yum Package Repositoriesxccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled highCCE-80792-5

Ensure gpgcheck Enabled for All yum Package Repositories

Rule IDxccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-ensure_gpgcheck_never_disabled:def:1
Time2021-03-21T20:15:22+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80792-5

References:  NT28(R15), 11, 2, 3, 9, 5.10.4.1, APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02, 3.4.8, CCI-001749, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), SA-12, SA-12(10), CM-11(a), CM-11(b), PR.DS-6, PR.DS-8, PR.IP-1, FAU_GEN.1.1.c, Req-6.2, SRG-OS-000366-GPOS-00153, SRG-OS-000366-VMM-001430, SRG-OS-000370-VMM-001460, SRG-OS-000404-VMM-001650

Description

To ensure signature checking is not disabled for any repos, remove any lines from files in /etc/yum.repos.d of the form:

gpgcheck=0

Rationale

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



sed -i 's/gpgcheck\s*=.*/gpgcheck=1/g' /etc/yum.repos.d/*


Complexity:low
Disruption:medium
Strategy:enable
- name: Grep for yum repo section names
  shell: grep -HEr '^\[.+\]' -r /etc/yum.repos.d/
  register: repo_grep_results
  ignore_errors: true
  changed_when: false
  tags:
    - ensure_gpgcheck_never_disabled
    - high_severity
    - enable_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80792-5
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1

- name: Set gpgcheck=1 for each yum repo
  ini_file:
    path: '{{ item[0] }}'
    section: '{{ item[1] }}'
    option: gpgcheck
    value: '1'
    no_extra_spaces: true
  loop: '{{ repo_grep_results.stdout | regex_findall( ''(.+\.repo):\[(.+)\]\n?'' )
    }}'
  tags:
    - ensure_gpgcheck_never_disabled
    - high_severity
    - enable_strategy
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80792-5
    - NIST-800-53-CM-5(3)
    - NIST-800-53-SI-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-171-3.4.8
    - PCI-DSS-Req-6.2
    - CJIS-5.10.4.1
OVAL test results details

check for existence of gpgcheck=0 in /etc/yum.repos.d/ files  oval:ssg-test_ensure_gpgcheck_never_disabled:tst:1  false

Following items have been found on the system:
PathContent
/etc/yum.repos.d/slack.repogpgcheck=0
/etc/yum.repos.d/cajita.repo_oldgpgcheck=0
Set GNOME3 Screensaver Inactivity Timeoutxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_idle_delay mediumCCE-80775-0

Set GNOME3 Screensaver Inactivity Timeout

Rule IDxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_idle_delay
Result
notapplicable
Multi-check ruleno
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80775-0

References:  1, 12, 15, 16, 5.5.5, DSS05.04, DSS05.10, DSS06.10, 3.1.10, CCI-000057, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, AC-11(a), CM-6(a), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.8, SRG-OS-000029-GPOS-00010

Description

The idle time-out value for inactivity in the GNOME3 desktop is configured via the idle-delay setting must be set under an appropriate configuration file(s) in the /etc/dconf/db/local.d directory and locked in /etc/dconf/db/local.d/locks directory to prevent user modification.

For example, to configure the system for a 15 minute delay, add the following to /etc/dconf/db/local.d/00-security-settings:

[org/gnome/desktop/session]
idle-delay=uint32 900
Once the setting has been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/desktop/session/idle-delay
After the settings have been set, run dconf update.

Rationale

A session time-out lock is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not logout because of the temporary nature of the absence. Rather than relying on the user to manually lock their operating system session prior to vacating the vicinity, GNOME3 can be configured to identify when a user's session has idled and take action to initiate a session lock.

Enable GNOME3 Screensaver Idle Activationxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_idle_activation_enabled mediumCCE-80774-3

Enable GNOME3 Screensaver Idle Activation

Rule IDxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_idle_activation_enabled
Result
notapplicable
Multi-check ruleno
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80774-3

References:  1, 12, 15, 16, 5.5.5, DSS05.04, DSS05.10, DSS06.10, 3.1.10, CCI-000057, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-11(a), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.8, SRG-OS-000029-GPOS-00010

Description

To activate the screensaver in the GNOME3 desktop after a period of inactivity, add or set idle-activation-enabled to true in /etc/dconf/db/local.d/00-security-settings. For example:

[org/gnome/desktop/screensaver]
idle-activation-enabled=true
Once the setting has been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/desktop/screensaver/idle-activation-enabled
After the settings have been set, run dconf update.

Rationale

A session time-out lock is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not logout because of the temporary nature of the absence. Rather than relying on the user to manually lock their operating system session prior to vacating the vicinity, GNOME desktops can be configured to identify when a user's session has idled and take action to initiate the session lock.

Enabling idle activation of the screensaver ensures the screensaver will be activated after the idle delay. Applications requiring continuous, real-time screen display (such as network management products) require the login session does not have administrator rights and the display station is located in a controlled-access area.

Implement Blank Screensaverxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_mode_blank mediumCCE-80778-4

Implement Blank Screensaver

Rule IDxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_mode_blank
Result
notapplicable
Multi-check ruleno
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80778-4

References:  1, 12, 15, 16, 5.5.5, DSS05.04, DSS05.10, DSS06.10, 3.1.10, CCI-000060, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, AC-11(1), CM-6(a), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.8

Description

To set the screensaver mode in the GNOME3 desktop to a blank screen, add or set picture-uri to string '' in /etc/dconf/db/local.d/00-security-settings. For example:

[org/gnome/desktop/screensaver]
picture-uri=''
Once the settings have been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/desktop/screensaver/picture-uri
After the settings have been set, run dconf update.

Rationale

Setting the screensaver mode to blank-only conceals the contents of the display from passersby.

Enable GNOME3 Screensaver Lock After Idle Periodxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_lock_enabled mediumCCE-80777-6

Enable GNOME3 Screensaver Lock After Idle Period

Rule IDxccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_lock_enabled
Result
notapplicable
Multi-check ruleno
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80777-6

References:  1, 12, 15, 16, 5.5.5, DSS05.04, DSS05.10, DSS06.10, 3.1.10, CCI-000056, CCI-000058, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), PR.AC-7, FMT_MOF_EXT.1, Req-8.1.8, SRG-OS-000028-GPOS-00009, SRG-OS-000030-GPOS-00011

Description

To activate locking of the screensaver in the GNOME3 desktop when it is activated, add or set lock-enabled to true in /etc/dconf/db/local.d/00-security-settings. For example:

[org/gnome/desktop/screensaver]
lock-enabled=true
Once the settings have been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/desktop/screensaver/lock-enabled
After the settings have been set, run dconf update.

Rationale

A session lock is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not want to logout because of the temporary nature of the absense.

Make sure that the dconf databases are up-to-date with regards to respective keyfilesxccdf_org.ssgproject.content_rule_dconf_db_up_to_date highCCE-81003-6

Make sure that the dconf databases are up-to-date with regards to respective keyfiles

Rule IDxccdf_org.ssgproject.content_rule_dconf_db_up_to_date
Result
notapplicable
Multi-check ruleno
Time2021-03-21T20:15:22+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-81003-6

References:  SRG-OS-000480-GPOS-00227

Description

By default, DConf uses a binary database as a data backend. The system-level database is compiled from keyfiles in the /etc/dconf/db/ directory by the

dconf update
command.

Rationale

Unlike text-based keyfiles, the binary database is impossible to check by OVAL. Therefore, in order to evaluate dconf configuration, both have to be true at the same time - configuration files have to be compliant, and the database needs to be more recent than those keyfiles, which gives confidence that it reflects them.

Install AIDExccdf_org.ssgproject.content_rule_package_aide_installed mediumCCE-80844-4

Install AIDE

Rule IDxccdf_org.ssgproject.content_rule_package_aide_installed
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-package_aide_installed:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80844-4

References:  NT28(R51), 1.4.1, 1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9, 5.10.1.3, APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3, CM-6(a), DE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3, Req-11.5, SRG-OS-000363-GPOS-00150

Description

The aide package can be installed with the following command:

$ sudo yum install aide

Rationale

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



Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "aide" ; then
    yum install -y "aide"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:enable
- name: Ensure aide is installed
  package:
    name: aide
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - package_aide_installed
    - medium_severity
    - enable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80844-4
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3


Complexity:low
Disruption:low
Strategy:enable
include install_aide

class install_aide {
  package { 'aide':
    ensure => 'installed',
  }
}


Complexity:low
Disruption:low
Strategy:enable

package --add=aide
OVAL test results details

package aide is installed  oval:ssg-test_package_aide_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_aide_installed:obj:1 of type rpminfo_object
Name
aide
Configure Periodic Execution of AIDExccdf_org.ssgproject.content_rule_aide_periodic_cron_checking mediumCCE-80676-0

Configure Periodic Execution of AIDE

Rule IDxccdf_org.ssgproject.content_rule_aide_periodic_cron_checking
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-aide_periodic_cron_checking:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80676-0

References:  NT28(R51), 1.4.2, 1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9, 5.10.1.3, APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06, CCI-001744, CCI-002699, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3, SI-7, SI-7(1), CM-6(a), DE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3, Req-11.5, SRG-OS-000363-GPOS-00150, SRG-OS-000446-GPOS-00200

Description

At a minimum, AIDE should be configured to run a weekly scan. 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. The usage of cron's special time codes, such as @daily and @weekly is acceptable.

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.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "aide" ; then
    yum install -y "aide"
fi

if ! grep -q "/usr/sbin/aide --check" /etc/crontab ; then
    echo "05 4 * * * root /usr/sbin/aide --check" >> /etc/crontab
else
    sed -i '/^.*\/usr\/sbin\/aide --check.*$/d' /etc/crontab
    echo "05 4 * * * root /usr/sbin/aide --check" >> /etc/crontab
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Ensure AIDE is installed
  package:
    name: '{{ item }}'
    state: present
  with_items:
    - aide
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_periodic_cron_checking
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80676-0
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3

- name: Configure Periodic Execution of AIDE
  cron:
    name: run AIDE check
    minute: 5
    hour: 4
    weekday: 0
    user: root
    job: /usr/sbin/aide --check
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_periodic_cron_checking
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80676-0
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3
OVAL test results details

package aide is installed  oval:ssg-test_package_aide_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_aide_installed:obj:1 of type rpminfo_object
Name
aide

run aide with cron  oval:ssg-test_aide_periodic_cron_checking:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_test_aide_periodic_cron_checking:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/crontab^(([0-9]*[\s]*[0-9]*[\s]*\*[\s]*\*[\s]*(\*|([0-7]|mon|tue|wed|thu|fri|sat|sun)|[0-7]-[0-7]))|@(hourly|daily|weekly))[\s]*root[\s]*/usr/sbin/aide[\s]*\-\-check.*$1

run aide with cron  oval:ssg-test_aide_crond_checking:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_test_aide_crond_checking:obj:1 of type textfilecontent54_object
PathFilenamePatternInstance
/etc/cron.d^.*$^(([0-9]*[\s]*[0-9]*[\s]*\*[\s]*\*[\s]*(\*|([0-7]|mon|tue|wed|thu|fri|sat|sun)|[0-7]-[0-7]))|@(hourly|daily|weekly))[\s]*root[\s]*/usr/sbin/aide[\s]*\-\-check.*$1

run aide with cron  oval:ssg-test_aide_var_cron_checking:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_aide_var_cron_checking:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/var/spool/cron/root^(([0-9]*[\s]*[0-9]*[\s]*\*[\s]*\*[\s]*(\*|([0-7]|mon|tue|wed|thu|fri|sat|sun)|[0-7]-[0-7]))|@(hourly|daily|weekly))[\s]*(root)?[\s]*/usr/sbin/aide[\s]*\-\-check.*$1

run aide with cron.(daily|weekly)  oval:ssg-test_aide_crontabs_checking:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_aide_crontabs_checking:obj:1 of type textfilecontent54_object
PathFilenamePatternInstance
^/etc/cron.(daily|weekly)$^.*$^\s*/usr/sbin/aide[\s]*\-\-check.*$1
Build and Test AIDE Databasexccdf_org.ssgproject.content_rule_aide_build_database mediumCCE-80675-2

Build and Test AIDE Database

Rule IDxccdf_org.ssgproject.content_rule_aide_build_database
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-aide_build_database:def:1
Time2021-03-21T20:15:22+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80675-2

References:  NT28(R51), 1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9, 5.10.1.3, APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3, CM-6(a), DE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3, Req-11.5

Description

Run the following command to generate a new database:

$ sudo /usr/sbin/aide --init
By default, the database will be written to the file /var/lib/aide/aide.db.new.gz. Storing the database, the configuration file /etc/aide.conf, and the binary /usr/sbin/aide (or hashes of these files), in a secure location (such as on read-only media) provides additional assurance about their integrity. The newly-generated database can be installed as follows:
$ sudo cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
To initiate a manual check, run the following command:
$ sudo /usr/sbin/aide --check
If this check produces any unexpected output, investigate.

Rationale

For AIDE to be effective, an initial database of "known-good" information about files must be captured and it should be able to be verified against the installed files.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

if ! rpm -q --quiet "aide" ; then
    yum install -y "aide"
fi

/usr/sbin/aide --init
/bin/cp -p /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: Ensure AIDE is installed
  package:
    name: '{{ item }}'
    state: present
  with_items:
    - aide
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_build_database
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80675-2
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3

- name: Build and Test AIDE Database
  command: /usr/sbin/aide --init
  changed_when: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_build_database
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80675-2
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3

- name: Check whether the stock AIDE Database exists
  stat:
    path: /var/lib/aide/aide.db.new.gz
  register: aide_database_stat
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_build_database
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80675-2
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3

- name: Stage AIDE Database
  copy:
    src: /var/lib/aide/aide.db.new.gz
    dest: /var/lib/aide/aide.db.gz
    backup: true
    remote_src: true
  when:
    - (aide_database_stat.stat.exists is defined and aide_database_stat.stat.exists)
    - ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - aide_build_database
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80675-2
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - CJIS-5.10.1.3
OVAL test results details

package aide is installed  oval:ssg-test_package_aide_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_aide_installed:obj:1 of type rpminfo_object
Name
aide

Testing existence of new aide database file  oval:ssg-test_aide_build_new_database_absolute_path:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_aide_build_new_database_absolute_path:obj:1 of type file_object
Filepath
Referenced variable has no values (oval:ssg-variable_aide_build_new_database_absolute_path:var:1).

Testing existence of operational aide database file  oval:ssg-test_aide_operational_database_absolute_path:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_aide_operational_database_absolute_path:obj:1 of type file_object
Filepath
Referenced variable has no values (oval:ssg-variable_aide_operational_database_absolute_path:var:1)
Verify File Hashes with RPMxccdf_org.ssgproject.content_rule_rpm_verify_hashes highCCE-80857-6

Verify File Hashes with RPM

Rule IDxccdf_org.ssgproject.content_rule_rpm_verify_hashes
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-rpm_verify_hashes:def:1
Time2021-03-21T20:15:48+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80857-6

References:  1.2.6, 11, 2, 3, 9, 5.10.4.1, APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02, 3.3.8, 3.4.1, CCI-000366, CCI-000663, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3), PR.DS-6, PR.DS-8, PR.IP-1, Req-11.5, SRG-OS-000480-GPOS-00227

Description

Without cryptographic integrity protections, system executables and files can be altered by unauthorized users without detection. The RPM package management system can check the hashes of installed software packages, including many that are important to system security. To verify that the cryptographic hash of system files and commands match vendor values, run the following command to list which files on the system have hashes that differ from what is expected by the RPM database:

$ rpm -Va | grep '^..5'
A "c" in the second column indicates that a file is a configuration file, which may appropriately be expected to change. If the file was not expected to change, investigate the cause of the change using audit logs or other means. The package can then be reinstalled to restore the file. Run the following command to determine which package owns the file:
$ rpm -qf FILENAME
The package can be reinstalled from a yum repository using the command:
$ sudo yum reinstall PACKAGENAME
Alternatively, the package can be reinstalled from trusted media using the command:
$ sudo rpm -Uvh PACKAGENAME

Rationale

The hashes of important files like system executables should match the information given by the RPM database. Executables with erroneous hashes could be a sign of nefarious activity on the system.

OVAL test results details

verify file md5 hashes  oval:ssg-test_files_fail_md5_hash:tst:1  true

No items have been found conforming to the following objects:
Object oval:ssg-object_files_fail_md5_hash:obj:1 of type rpmverifyfile_object
BehaviorsNameEpochVersionReleaseArchFilepathFilter
no value.*.*.*.*.*^/(bin|sbin|lib|lib64|usr)/.+$oval:ssg-state_files_fail_md5_hash:ste:1
Verify and Correct File Permissions with RPMxccdf_org.ssgproject.content_rule_rpm_verify_permissions highCCE-80858-4

Verify and Correct File Permissions with RPM

Rule IDxccdf_org.ssgproject.content_rule_rpm_verify_permissions
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-rpm_verify_permissions:def:1
Time2021-03-21T20:15:53+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80858-4

References:  1.8.1.4, 1.8.1.5, 1.8.1.6, 6.1.1, 6.1.2, 6.1.3, 6.1.4, 6.1.5, 6.1.6, 6.1.7, 6.1.8, 6.1.9, 1, 11, 12, 13, 14, 15, 16, 18, 3, 5, 6, 9, 5.10.4.1, APO01.06, APO11.04, BAI03.05, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.07, DSS06.02, MEA02.01, 3.3.8, 3.4.1, CCI-001493, CCI-001494, CCI-001495, CCI-001496, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 7.6, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.5.1, A.12.6.2, A.12.7.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3), CM-6(a), PR.AC-4, PR.DS-5, PR.IP-1, PR.PT-1, Req-11.5, SRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098, SRG-OS-000258-GPOS-00099, SRG-OS-000278-GPOS-00108

Description

The RPM package management system can check file access permissions of installed software packages, including many that are important to system security. Verify that the file permissions of system files and commands match vendor values. Check the file permissions with the following command:

$ sudo rpm -Va | awk '{ if (substr($0,2,1)=="M") print $NF }'
Output indicates files that do not match vendor defaults. After locating a file with incorrect permissions, run the following command to determine which package owns it:
$ rpm -qf FILENAME

Next, run the following command to reset its permissions to the correct values:
$ sudo rpm --setperms PACKAGENAME

Rationale

Permissions on system binaries and configuration files that are too generous could allow an unauthorized user to gain privileges that they should not have. The permissions set by the vendor should be maintained. Any deviations from this baseline should be investigated.

Warnings
warning  Profiles may require that specific files have stricter file permissions than defined by the vendor. Such files will be reported as a finding and need to be evaluated according to your policy and deployment environment.


Complexity:high
Disruption:medium
Strategy:restrict

# Declare array to hold set of RPM packages we need to correct permissions for
declare -A SETPERMS_RPM_DICT

# Create a list of files on the system having permissions different from what
# is expected by the RPM database
readarray -t FILES_WITH_INCORRECT_PERMS < <(rpm -Va --nofiledigest | awk '{ if (substr($0,2,1)=="M") print $NF }')

for FILE_PATH in "${FILES_WITH_INCORRECT_PERMS[@]}"
do
	RPM_PACKAGE=$(rpm -qf "$FILE_PATH")
	# Use an associative array to store packages as it's keys, not having to care about duplicates.
	SETPERMS_RPM_DICT["$RPM_PACKAGE"]=1
done

# For each of the RPM packages left in the list -- reset its permissions to the
# correct values
for RPM_PACKAGE in "${!SETPERMS_RPM_DICT[@]}"
do
	rpm --setperms "${RPM_PACKAGE}"
done


Complexity:high
Disruption:medium
Strategy:restrict
- name: Read list of files with incorrect permissions
  command: rpm -Va --nodeps --nosignature --nofiledigest --nosize --nomtime --nordev
    --nocaps --nolinkto --nouser --nogroup
  args:
    warn: false
  register: files_with_incorrect_permissions
  failed_when: files_with_incorrect_permissions.rc > 1
  changed_when: false
  check_mode: false
  tags:
    - rpm_verify_permissions
    - high_severity
    - restrict_strategy
    - high_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80858-4
    - NIST-800-53-CM-6(d)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - PCI-DSS-Req-11.5
    - CJIS-5.10.4.1

- name: Create list of packages
  command: rpm -qf "{{ item }}"
  args:
    warn: false
  with_items: '{{ files_with_incorrect_permissions.stdout_lines | map(''regex_findall'',
    ''^[.]+[M]+.* (\/.*)'', ''\1'') | map(''join'') | select(''match'', ''(\/.*)'')
    | list | unique }}'
  register: list_of_packages
  changed_when: false
  check_mode: false
  when: (files_with_incorrect_permissions.stdout_lines | length > 0)
  tags:
    - rpm_verify_permissions
    - high_severity
    - restrict_strategy
    - high_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80858-4
    - NIST-800-53-CM-6(d)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - PCI-DSS-Req-11.5
    - CJIS-5.10.4.1

- name: Correct file permissions with RPM
  command: rpm --setperms '{{ item }}'
  args:
    warn: false
  with_items: '{{ list_of_packages.results | map(attribute=''stdout_lines'') | list
    | unique }}'
  when: (files_with_incorrect_permissions.stdout_lines | length > 0)
  tags:
    - rpm_verify_permissions
    - high_severity
    - restrict_strategy
    - high_complexity
    - medium_disruption
    - no_reboot_needed
    - CCE-80858-4
    - NIST-800-53-CM-6(d)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - PCI-DSS-Req-11.5
    - CJIS-5.10.4.1
OVAL test results details

mode of all files matches local rpm database  oval:ssg-test_verify_all_rpms_mode:tst:1  false

Following items have been found on the system:
NameEpochVersionReleaseArchFilepathExtended nameSize differsMode differsMd5 differsDevice differsLink mismatchOwnership differsGroup differsMtime differsCapabilities differConfiguration fileDocumentation fileGhost fileLicense fileReadme file
firewalld(none)0.8.22.el8noarch/etc/firewalld/firewalld.conffirewalld-0:0.8.2-2.el8.noarchpassfailnot performedpasspasspasspassfailpasstruefalsefalsefalsefalse
Configure SSH to use System Crypto Policyxccdf_org.ssgproject.content_rule_configure_ssh_crypto_policy mediumCCE-80939-2

Configure SSH to use System Crypto Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_ssh_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_ssh_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80939-2

References:  5.2.20, AC-17(a), AC-17(2), CM-6(a), MA-4(6), SC-13, SRG-OS-000250-GPOS-00093

Description

Crypto Policies provide a centralized control over crypto algorithms usage of many packages. SSH is supported by crypto policy, but the SSH configuration may be set up to ignore it. To check that Crypto Policies settings are configured correctly, ensure that the CRYPTO_POLICY variable is either commented or not set at all in the /etc/sysconfig/sshd.

Rationale

Overriding the system crypto policy makes the behavior of the SSH service violate expectations, and makes system configuration more fragmented.

OVAL test results details

Check that the SSH configuration mandates usage of system-wide crypto policies.  oval:ssg-test_configure_ssh_crypto_policy:tst:1  true

No items have been found conforming to the following objects:
Object oval:ssg-object_configure_ssh_crypto_policy:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/sysconfig/sshd^\s*CRYPTO_POLICY\s*=.*$1
Configure BIND to use System Crypto Policyxccdf_org.ssgproject.content_rule_configure_bind_crypto_policy mediumCCE-80934-3

Configure BIND to use System Crypto Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_bind_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_bind_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80934-3

References:  SC-13, SC-12(2), SC-12(3), SRG-OS-000423-GPOS-00187, SRG-OS-000426-GPOS-00190

Description

Crypto Policies provide a centralized control over crypto algorithms usage of many packages. BIND is supported by crypto policy, but the BIND configuration may be set up to ignore it. To check that Crypto Policies settings are configured correctly, ensure that the /etc/named.conf includes the appropriate configuration: In the options section of /etc/named.conf, make sure that the following line is not commented out or superseded by later includes: include "/etc/crypto-policies/back-ends/bind.config";

Rationale

Overriding the system crypto policy makes the behavior of the BIND service violate expectations, and makes system configuration more fragmented.

OVAL test results details

package bind is removed  oval:ssg-test_package_bind_removed:tst:1  true

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_package_bind_removed:obj:1 of type rpminfo_object
Name
bind

Check that the configuration includes the policy config file.  oval:ssg-test_configure_bind_crypto_policy:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_configure_bind_crypto_policy:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/named.conf^\s*include\s+"/etc/crypto-policies/back-ends/bind.config"\s*;\s*$1
Configure OpenSSL library to use System Crypto Policyxccdf_org.ssgproject.content_rule_configure_openssl_crypto_policy mediumCCE-80938-4

Configure OpenSSL library to use System Crypto Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_openssl_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_openssl_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80938-4

References:  AC-17(a), AC-17(2), CM-6(a), MA-4(6), SC-13, SC-12(2), SC-12(3), SRG-OS-000250-GPOS-00093

Description

Crypto Policies provide a centralized control over crypto algorithms usage of many packages. OpenSSL is supported by crypto policy, but the OpenSSL configuration may be set up to ignore it. To check that Crypto Policies settings are configured correctly, you have to examine the OpenSSL config file available under /etc/pki/tls/openssl.cnf. This file has the ini format, and it enables crypto policy support if there is a [ crypto_policy ] section that contains the .include /etc/crypto-policies/back-ends/opensslcnf.config directive.

Rationale

Overriding the system crypto policy makes the behavior of the Java runtime violates expectations, and makes system configuration more fragmented.

OVAL test results details

Check that the configuration mandates usage of system-wide crypto policies.  oval:ssg-test_configure_openssl_crypto_policy:tst:1  true

Following items have been found on the system:
PathContent
/etc/pki/tls/openssl.cnf [ crypto_policy ] .include /etc/crypto-policies/back-ends/opensslcnf.config
Configure Libreswan to use System Crypto Policyxccdf_org.ssgproject.content_rule_configure_libreswan_crypto_policy mediumCCE-80937-6

Configure Libreswan to use System Crypto Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_libreswan_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_libreswan_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80937-6

References:  CM-6(a), MA-4(6), SC-13, SC-12(2), SC-12(3), SRG-OS-000033-GPOS-00014

Description

Crypto Policies provide a centralized control over crypto algorithms usage of many packages. Libreswan is supported by system crypto policy, but the Libreswan configuration may be set up to ignore it. To check that Crypto Policies settings are configured correctly, ensure that the /etc/ipsec.conf includes the appropriate configuration file. In /etc/ipsec.conf, make sure that the following line is not commented out or superseded by later includes: include /etc/crypto-policies/back-ends/libreswan.config

Rationale

Overriding the system crypto policy makes the behavior of the Libreswan service violate expectations, and makes system configuration more fragmented.

OVAL test results details

package libreswan is installed  oval:ssg-test_package_libreswan_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
libreswanx86_64(none)7.el8_33.320:3.32-7.el8_3199e2f91fd431d51libreswan-0:3.32-7.el8_3.x86_64

Check that the libreswan configuration includes the crypto policy config file  oval:ssg-test_configure_libreswan_crypto_policy:tst:1  true

Following items have been found on the system:
PathContent
/etc/ipsec.confinclude /etc/crypto-policies/back-ends/libreswan.config # It is best to add your IPsec connections as separate files in /etc/ipsec.d/
Configure System Cryptography Policyxccdf_org.ssgproject.content_rule_configure_crypto_policy highCCE-80935-0

Configure System Cryptography Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80935-0

References:  1.10, 1.11, AC-17(a), AC-17(2), CM-6(a), MA-4(6), SC-13, SC-12(2), SC-12(3), SRG-OS-000396-GPOS-00176, SRG-OS-000393-GPOS-00173, SRG-OS-000394-GPOS-00174

Description

To configure the system cryptography policy to use ciphers only from the DEFAULT policy, run the following command:

$ sudo update-crypto-policies --set DEFAULT
The rule checks if settings for selected crypto policy are configured as expected. Configuration files in the /etc/crypto-policies/back-ends are either symlinks to correct files provided by Crypto-policies package or they are regular files in case crypto policy customizations are applied. Crypto policies may be customized by crypto policy modules, in which case it is delimited from the base policy using a colon.

Rationale

Centralized cryptographic policies simplify applying secure ciphers across an operating system and the applications that run on that operating system. Use of weak or untested encryption algorithms undermines the purposes of utilizing encryption to protect data.

Warnings
warning  The system needs to be rebooted for these changes to take effect.
warning  System Crypto Modules must be provided by a vendor that undergoes FIPS-140 certifications. FIPS-140 is applicable to all Federal agencies that use cryptographic-based security systems to protect sensitive information in computer and telecommunication systems (including voice systems) as defined in Section 5131 of the Information Technology Management Reform Act of 1996, Public Law 104-106. This standard shall be used in designing and implementing cryptographic modules that Federal departments and agencies operate or are operated for them under contract. See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf To meet this, the system has to have cryptographic software provided by a vendor that has undergone this certification. This means providing documentation, test results, design information, and independent third party review by an accredited lab. While open source software is capable of meeting this, it does not meet FIPS-140 unless the vendor submits to this process.
OVAL test results details

check for crypto policy correctly configured in /etc/crypto-policies/config  oval:ssg-test_configure_crypto_policy:tst:1  true

Following items have been found on the system:
PathContent
/etc/crypto-policies/configDEFAULT

check for crypto policy correctly configured in /etc/crypto-policies/state/current  oval:ssg-test_configure_crypto_policy_current:tst:1  true

Following items have been found on the system:
PathContent
/etc/crypto-policies/state/currentDEFAULT

Check if update-crypto-policies has been run  oval:ssg-test_crypto_policies_updated:tst:1  true

Following items have been found on the system:
Var refValue
oval:ssg-variable_crypto_policies_config_file_age:var:18998431

Check if /etc/crypto-policies/back-ends/nss.config exists  oval:ssg-test_crypto_policy_nss_config:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/crypto-policies/back-ends/nss.configregular00429rw-r--r-- 
Configure Kerberos to use System Crypto Policyxccdf_org.ssgproject.content_rule_configure_kerberos_crypto_policy mediumCCE-80936-8

Configure Kerberos to use System Crypto Policy

Rule IDxccdf_org.ssgproject.content_rule_configure_kerberos_crypto_policy
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-configure_kerberos_crypto_policy:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80936-8

References:  SC-13, SC-12(2), SC-12(3), SRG-OS-000120-GPOS-00061

Description

Crypto Policies provide a centralized control over crypto algorithms usage of many packages. Kerberos is supported by crypto policy, but it's configuration may be set up to ignore it. To check that Crypto Policies settings for Kerberos are configured correctly, examine that there is a symlink at /etc/krb5.conf.d/crypto-policies targeting /etc/cypto-policies/back-ends/krb5.config. If the symlink exists, kerberos is configured to use the system-wide crypto policy settings.

Rationale

Overriding the system crypto policy makes the behavior of Kerberos violate expectations, and makes system configuration more fragmented.

OVAL test results details

Check if kerberos configuration symlink and crypto policy kerberos backend symlink point to same file  oval:ssg-test_configure_kerberos_crypto_policy_symlink:tst:1  true

Following items have been found on the system:
Var refValue
oval:ssg-var_symlink_kerberos_crypto_policy_configuration:var:1/usr/share/crypto-policies/DEFAULT/krb5.txt

Check if kerberos configuration symlink links to the crypto-policy backend file  oval:ssg-test_configure_kerberos_crypto_policy_nosymlink:tst:1  false

Following items have been found on the system:
Var refValue
oval:ssg-var_symlink_kerberos_crypto_policy_configuration:var:1/usr/share/crypto-policies/DEFAULT/krb5.txt
Install Intrusion Detection Softwarexccdf_org.ssgproject.content_rule_install_hids highCCE-80831-1

Install Intrusion Detection Software

Rule IDxccdf_org.ssgproject.content_rule_install_hids
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-install_hids:def:1
Time2021-03-21T20:15:53+01:00
Severityhigh
Identifiers and References

Identifiers:  CCE-80831-1

References:  1, 12, 13, 14, 15, 16, 18, 7, 8, 9, APO01.06, APO13.01, DSS01.03, DSS01.05, DSS03.05, DSS05.02, DSS05.04, DSS05.07, DSS06.02, CCI-001263, 4.3.3.4, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.2, SR 7.1, SR 7.6, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), DE.CM-1, PR.AC-5, PR.DS-5, PR.PT-4, Req-11.4

Description

The base Red Hat Enterprise Linux 8 platform already includes a sophisticated auditing system that can detect intruder activity, as well as SELinux, which provides host-based intrusion prevention capabilities by confining privileged programs and user sessions which may become compromised.

Rationale

Host-based intrusion detection tools provide a system-level defense when an intruder gains access to a system or network.

Warnings
warning  In DoD environments, supplemental intrusion detection and antivirus tools, such as the McAfee Host-based Security System, are available to integrate with existing infrastructure. Per DISA guidance, when these supplemental tools interfere with proper functioning of SELinux, SELinux takes precedence. Should further clarification be required, DISA contact information is published publicly at https://public.cyber.mil/stigs/
OVAL test results details

Runtime Libraries package is installed  oval:ssg-test_mcafee_runtime_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_mcafee_runtime_installed:obj:1 of type rpminfo_object
Name
MFErt

Agent package is installed  oval:ssg-test_mcafee_management_agent:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_mcafee_management_agent:obj:1 of type rpminfo_object
Name
MFEcma

McAfee ACCM installed  oval:ssg-test_mcafee_accm_exists:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_mcafee_accm_exists:obj:1 of type file_object
PathFilename
/opt/McAfee/accm/binaccm

McAfee IPS is installed  oval:ssg-test_mcafee_hbss_hips_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_mcafee_hbss_hips_installed:obj:1 of type rpminfo_object
Name
MFEhiplsm

McAfee Policy Auditor installed  oval:ssg-test_mcafee_auditengine_exists:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_mcafee_auditengine_exists:obj:1 of type file_object
PathFilename
/opt/McAfee/auditengine/binauditmanager

/selinux/enforce is 1  oval:ssg-test_selinux_enforcing:tst:1  true

Following items have been found on the system:
PathContent
/etc/selinux/configSELINUX=enforcing
Verify /boot/grub2/grub.cfg Group Ownershipxccdf_org.ssgproject.content_rule_file_groupowner_grub2_cfg mediumCCE-80800-6

Verify /boot/grub2/grub.cfg Group Ownership

Rule IDxccdf_org.ssgproject.content_rule_file_groupowner_grub2_cfg
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_groupowner_grub2_cfg:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80800-6

References:  1.5.1, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 3.4.5, CCI-000225, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-7.1

Description

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.

OVAL test results details

Verify if /sys/firmware/efi folder exists  oval:ssg-test_efi_dir_existence:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_file_sys_firmware_efi:obj:1 of type file_object
PathFilename
/sys/firmware/efino value

Verify group ownership of /boot/grub2/grub.cfg  oval:ssg-test_file_groupowner_grub2_cfg:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/boot/grub2/grub.cfgregular006441rw-r--r-- 
Verify /boot/grub2/grub.cfg User Ownershipxccdf_org.ssgproject.content_rule_file_owner_grub2_cfg mediumCCE-80805-5

Verify /boot/grub2/grub.cfg User Ownership

Rule IDxccdf_org.ssgproject.content_rule_file_owner_grub2_cfg
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_owner_grub2_cfg:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80805-5

References:  1.5.1, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 3.4.5, CCI-000225, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-7.1

Description

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.

OVAL test results details

Verify if /sys/firmware/efi folder exists  oval:ssg-test_efi_dir_existence:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_file_sys_firmware_efi:obj:1 of type file_object
PathFilename
/sys/firmware/efino value

Testing user ownership of /boot/grub2/grub.cfg  oval:ssg-test_file_owner_grub2_cfg:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/boot/grub2/grub.cfgregular006441rw-r--r-- 
Install libreswan Packagexccdf_org.ssgproject.content_rule_package_libreswan_installed mediumCCE-80845-1

Install libreswan Package

Rule IDxccdf_org.ssgproject.content_rule_package_libreswan_installed
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-package_libreswan_installed:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80845-1

References:  12, 15, 3, 5, 8, APO13.01, DSS01.04, DSS05.02, DSS05.03, DSS05.04, CCI-001130, CCI-001131, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, SR 1.13, SR 2.6, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.4, A.11.2.6, A.13.1.1, A.13.2.1, A.14.1.3, A.15.1.1, A.15.2.1, A.6.2.1, A.6.2.2, CM-6(a), PR.AC-3, PR.MA-2, PR.PT-4, Req-4.1, SRG-OS-000480-GPOS-00227, SRG-OS-000120-GPOS-00061

Description

The Libreswan package provides an implementation of IPsec and IKE, which permits the creation of secure tunnels over untrusted networks. The libreswan package can be installed with the following command:

$ sudo yum install libreswan

Rationale

Providing the ability for remote users or systems to initiate a secure VPN connection protects information when it is transmitted over a wide area network.

OVAL test results details

package libreswan is installed  oval:ssg-test_package_libreswan_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
libreswanx86_64(none)7.el8_33.320:3.32-7.el8_3199e2f91fd431d51libreswan-0:3.32-7.el8_3.x86_64
Ensure Log Files Are Owned By Appropriate Userxccdf_org.ssgproject.content_rule_rsyslog_files_ownership mediumCCE-80861-8

Ensure Log Files Are Owned By Appropriate User

Rule IDxccdf_org.ssgproject.content_rule_rsyslog_files_ownership
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-rsyslog_files_ownership:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80861-8

References:  NT28(R46), NT28(R5), 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, CCI-001314, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-10.5.1, Req-10.5.2

Description

The owner of all log files written by rsyslog should be root. 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 owner:

$ ls -l LOGFILE
If the owner is not root, run the following command to correct this:
$ sudo chown root LOGFILE

Rationale

The log files generated by rsyslog contain valuable information regarding system configuration, user authentication, and other such information. Log files should be protected from unauthorized access.

OVAL test results details

System log files are owned by root  oval:ssg-test_rsyslog_files_ownership:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/var/log/cronregular001935rw------- 
/var/log/boot.logregular006836rw------- 
/var/log/spoolerregular000rw------- 
/var/log/secureregular001677rw------- 
/var/log/messagesregular0088232rw------- 
/var/log/maillogregular000rw------- 
Ensure Log Files Are Owned By Appropriate Groupxccdf_org.ssgproject.content_rule_rsyslog_files_groupownership mediumCCE-80860-0

Ensure Log Files Are Owned By Appropriate Group

Rule IDxccdf_org.ssgproject.content_rule_rsyslog_files_groupownership
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-rsyslog_files_groupownership:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80860-0

References:  NT28(R46), NT28(R5), 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, CCI-001314, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-10.5.1, Req-10.5.2

Description

The group-owner of all log files written by rsyslog should be root. 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 group owner:

$ ls -l LOGFILE
If the owner is not root, run the following command to correct this:
$ sudo chgrp root LOGFILE

Rationale

The log files generated by rsyslog contain valuable information regarding system configuration, user authentication, and other such information. Log files should be protected from unauthorized access.

OVAL test results details

System log files are owned by root group  oval:ssg-test_rsyslog_files_groupownership:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/var/log/cronregular001935rw------- 
/var/log/boot.logregular006836rw------- 
/var/log/spoolerregular000rw------- 
/var/log/secureregular001677rw------- 
/var/log/messagesregular0088232rw------- 
/var/log/maillogregular000rw------- 
Ensure System Log Files Have Correct Permissionsxccdf_org.ssgproject.content_rule_rsyslog_files_permissions mediumCCE-80862-6

Ensure System Log Files Have Correct Permissions

Rule IDxccdf_org.ssgproject.content_rule_rsyslog_files_permissions
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-rsyslog_files_permissions:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80862-6

References:  NT28(R36), 4.2.1.3, CCI-001314, CM-6(a), AC-6(1), Req-10.5.1, Req-10.5.2

Description

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.

OVAL test results details

Permissions of system log files are correct  oval:ssg-test_rsyslog_files_permissions:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/var/log/cronregular001935rw------- 
/var/log/boot.logregular006836rw------- 
/var/log/spoolerregular000rw------- 
/var/log/secureregular001677rw------- 
/var/log/messagesregular0088232rw------- 
/var/log/maillogregular000rw------- 
Ensure Logrotate Runs Periodicallyxccdf_org.ssgproject.content_rule_ensure_logrotate_activated mediumCCE-80794-1

Ensure Logrotate Runs Periodically

Rule IDxccdf_org.ssgproject.content_rule_ensure_logrotate_activated
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-ensure_logrotate_activated:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80794-1

References:  NT28(R43), NT12(R18), 4.3, 1, 14, 15, 16, 3, 5, 6, APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01, CCI-000366, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, CM-6(a), PR.PT-1, Req-10.7

Description

The logrotate utility allows for the automatic rotation of log files. The frequency of rotation is specified in /etc/logrotate.conf, which triggers a cron task. To configure logrotate to run daily, add or correct the following line in /etc/logrotate.conf:

# rotate log files frequency
daily

Rationale

Log files that are not properly rotated run the risk of growing so large that they fill up the /var/log partition. Valuable logging information could be lost if the /var/log partition becomes full.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then

LOGROTATE_CONF_FILE="/etc/logrotate.conf"
CRON_DAILY_LOGROTATE_FILE="/etc/cron.daily/logrotate"

# daily rotation is configured
grep -q "^daily$" $LOGROTATE_CONF_FILE|| echo "daily" >> $LOGROTATE_CONF_FILE

# remove any line configuring weekly, monthly or yearly rotation
sed -i -r "/^(weekly|monthly|yearly)$/d" $LOGROTATE_CONF_FILE

# configure cron.daily if not already
if ! grep -q "^[[:space:]]*/usr/sbin/logrotate[[:alnum:][:blank:][:punct:]]*$LOGROTATE_CONF_FILE$" $CRON_DAILY_LOGROTATE_FILE; then
	echo "#!/bin/sh" > $CRON_DAILY_LOGROTATE_FILE
	echo "/usr/sbin/logrotate $LOGROTATE_CONF_FILE" >> $CRON_DAILY_LOGROTATE_FILE
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:configure
- name: Configure daily log rotation in /etc/logrotate.conf
  lineinfile:
    create: true
    dest: /etc/logrotate.conf
    regexp: ^daily$
    line: daily
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - ensure_logrotate_activated
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80794-1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7

- name: Make sure daily log rotation setting is not overriden in /etc/logrotate.conf
  lineinfile:
    create: false
    dest: /etc/logrotate.conf
    regexp: ^(weekly|monthly|yearly)$
    state: absent
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - ensure_logrotate_activated
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80794-1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7

- name: Configure cron.daily if not already
  block:

    - name: Add shebang
      lineinfile:
        path: /etc/cron.daily/logrotate
        line: '#!/bin/sh'
        insertbefore: BOF
        create: true

    - name: Add logrotate call
      lineinfile:
        path: /etc/cron.daily/logrotate
        line: /usr/sbin/logrotate /etc/logrotate.conf
        regexp: ^[\s]*/usr/sbin/logrotate[\s\S]*/etc/logrotate.conf$
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - ensure_logrotate_activated
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80794-1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
OVAL test results details

Tests the presence of daily setting in /etc/logrotate.conf file  oval:ssg-test_logrotate_conf_daily_setting:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_logrotate_conf_daily_setting:obj:1 of type textfilecontent54_object
BehaviorsFilepathPatternInstanceFilter
no value/etc/logrotate.conf(?:daily)*.*(?=[\n][\s]*daily)(.*)$1oval:ssg-state_another_rotate_interval_after_daily:ste:1

Tests the existence of /etc/cron.daily/logrotate file (and verify it actually calls logrotate utility)  oval:ssg-test_cron_daily_logrotate_existence:tst:1  true

Following items have been found on the system:
PathContent
/etc/cron.daily/logrotate /usr/sbin/logrotate /etc/logrotate.conf
Verify User Who Owns shadow Filexccdf_org.ssgproject.content_rule_file_owner_etc_shadow mediumCCE-80804-8

Verify User Who Owns shadow File

Rule IDxccdf_org.ssgproject.content_rule_file_owner_etc_shadow
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_owner_etc_shadow:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80804-8

References:  NT28(R36), 6.1.3, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the owner of /etc/shadow, run the command:

$ sudo chown root /etc/shadow 

Rationale

The /etc/shadow file contains the list of local system accounts and stores password hashes. Protection of this file is critical for system security. Failure to give ownership of this file to root provides the designated owner with access to sensitive information which could weaken the system security posture.

OVAL test results details

Testing user ownership of /etc/shadow  oval:ssg-test_file_owner_etc_shadow:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/shadowregular001066--------- 
Verify Permissions on passwd Filexccdf_org.ssgproject.content_rule_file_permissions_etc_passwd mediumCCE-80812-1

Verify Permissions on passwd File

Rule IDxccdf_org.ssgproject.content_rule_file_permissions_etc_passwd
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_permissions_etc_passwd:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80812-1

References:  6.1.2, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the permissions of /etc/passwd, run the command:

$ sudo chmod 0644 /etc/passwd

Rationale

If the /etc/passwd file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the list of accounts on the system and associated information, and protection of this file is critical for system security.

OVAL test results details

Testing mode of /etc/passwd  oval:ssg-test_file_permissions_etc_passwd:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/passwdregular001686rw-r--r-- 
Verify Permissions on shadow Filexccdf_org.ssgproject.content_rule_file_permissions_etc_shadow mediumCCE-80813-9

Verify Permissions on shadow File

Rule IDxccdf_org.ssgproject.content_rule_file_permissions_etc_shadow
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_permissions_etc_shadow:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80813-9

References:  NT28(R36), 6.1.3, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the permissions of /etc/shadow, run the command:

$ sudo chmod 0000 /etc/shadow

Rationale

The /etc/shadow file contains the list of local system accounts and stores password hashes. Protection of this file is critical for system security. Failure to give ownership of this file to root provides the designated owner with access to sensitive information which could weaken the system security posture.

OVAL test results details

Testing mode of /etc/shadow  oval:ssg-test_file_permissions_etc_shadow:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/shadowregular001066--------- 
Verify Group Who Owns group Filexccdf_org.ssgproject.content_rule_file_groupowner_etc_group mediumCCE-80796-6

Verify Group Who Owns group File

Rule IDxccdf_org.ssgproject.content_rule_file_groupowner_etc_group
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_groupowner_etc_group:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80796-6

References:  6.1.4, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the group owner of /etc/group, run the command:

$ sudo chgrp root /etc/group

Rationale

The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.

OVAL test results details

Testing group ownership of /etc/group  oval:ssg-test_file_groupowner_etc_group:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/groupregular00765rw-r--r-- 
Verify Group Who Owns passwd Filexccdf_org.ssgproject.content_rule_file_groupowner_etc_passwd mediumCCE-80798-2

Verify Group Who Owns passwd File

Rule IDxccdf_org.ssgproject.content_rule_file_groupowner_etc_passwd
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_groupowner_etc_passwd:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80798-2

References:  6.1.2, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the group owner of /etc/passwd, run the command:

$ sudo chgrp root /etc/passwd

Rationale

The /etc/passwd file contains information about the users that are configured on the system. Protection of this file is critical for system security.

OVAL test results details

Testing group ownership of /etc/passwd  oval:ssg-test_file_groupowner_etc_passwd:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/passwdregular001686rw-r--r-- 
Verify Permissions on group Filexccdf_org.ssgproject.content_rule_file_permissions_etc_group mediumCCE-80810-5

Verify Permissions on group File

Rule IDxccdf_org.ssgproject.content_rule_file_permissions_etc_group
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_permissions_etc_group:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80810-5

References:  6.1.4, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the permissions of /etc/passwd, run the command:

$ sudo chmod 0644 /etc/passwd

Rationale

The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.

OVAL test results details

Testing mode of /etc/group  oval:ssg-test_file_permissions_etc_group:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/groupregular00765rw-r--r-- 
Verify User Who Owns passwd Filexccdf_org.ssgproject.content_rule_file_owner_etc_passwd mediumCCE-80803-0

Verify User Who Owns passwd File

Rule IDxccdf_org.ssgproject.content_rule_file_owner_etc_passwd
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_owner_etc_passwd:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80803-0

References:  6.1.2, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the owner of /etc/passwd, run the command:

$ sudo chown root /etc/passwd 

Rationale

The /etc/passwd file contains information about the users that are configured on the system. Protection of this file is critical for system security.

OVAL test results details

Testing user ownership of /etc/passwd  oval:ssg-test_file_owner_etc_passwd:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/passwdregular001686rw-r--r-- 
Verify User Who Owns group Filexccdf_org.ssgproject.content_rule_file_owner_etc_group mediumCCE-80801-4

Verify User Who Owns group File

Rule IDxccdf_org.ssgproject.content_rule_file_owner_etc_group
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_owner_etc_group:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80801-4

References:  6.1.4, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the owner of /etc/group, run the command:

$ sudo chown root /etc/group 

Rationale

The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.

OVAL test results details

Testing user ownership of /etc/group  oval:ssg-test_file_owner_etc_group:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/groupregular00765rw-r--r-- 
Verify Group Who Owns shadow Filexccdf_org.ssgproject.content_rule_file_groupowner_etc_shadow mediumCCE-80799-0

Verify Group Who Owns shadow File

Rule IDxccdf_org.ssgproject.content_rule_file_groupowner_etc_shadow
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-file_groupowner_etc_shadow:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80799-0

References:  6.1.3, 12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-8.7.c

Description

To properly set the group owner of /etc/shadow, run the command:

$ sudo chgrp root /etc/shadow

Rationale

The /etc/shadow file stores password hashes. Protection of this file is critical for system security.

OVAL test results details

Testing group ownership of /etc/shadow  oval:ssg-test_file_groupowner_etc_shadow:tst:1  true

Following items have been found on the system:
PathTypeUIDGIDSize (B)Permissions
/etc/shadowregular001066--------- 
Set SSH Idle Timeout Intervalxccdf_org.ssgproject.content_rule_sshd_set_idle_timeout mediumCCE-80906-1

Set SSH Idle Timeout Interval

Rule IDxccdf_org.ssgproject.content_rule_sshd_set_idle_timeout
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-sshd_set_idle_timeout:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80906-1

References:  NT28(R29), 5.2.13, 1, 12, 13, 14, 15, 16, 18, 3, 5, 7, 8, 5.5.6, APO13.01, BAI03.01, BAI03.02, BAI03.03, DSS01.03, DSS03.05, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.1.11, CCI-000879, CCI-001133, CCI-002361, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 6.2, A.12.4.1, A.12.4.3, A.14.1.1, A.14.2.1, A.14.2.5, A.18.1.4, A.6.1.2, A.6.1.5, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, CM-6(a), AC-17(a), AC-2(5), AC-12, AC-17(a), SC-10, CM-6(a), DE.CM-1, DE.CM-3, PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.IP-2, Req-8.1.8, SRG-OS-000126-GPOS-00066, SRG-OS-000163-GPOS-00072, SRG-OS-000279-GPOS-00109, SRG-OS-000395-GPOS-00175, SRG-OS-000480-VMM-002000

Description

SSH allows administrators to set an idle timeout interval. After this interval has passed, the idle user will be automatically logged out.

To set an idle timeout interval, edit the following line in /etc/ssh/sshd_config as follows:

ClientAliveInterval 900


The timeout interval is given in seconds. For example, have a timeout of 10 minutes, set interval to 600.

If a shorter timeout has already been set for the login shell, that value will preempt any SSH setting made in /etc/ssh/sshd_config. Keep in mind that some processes may stop SSH from correctly detecting that the user is idle.

Rationale

Terminating an idle ssh session within a short time period reduces the window of opportunity for unauthorized personnel to take control of a management session enabled on the console or console port that has been let unattended.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


sshd_idle_timeout_value="900"
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append '/etc/ssh/sshd_config' '^ClientAliveInterval' $sshd_idle_timeout_value 'CCE-80906-1' '%s %s'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value sshd_idle_timeout_value # promote to variable
  set_fact:
    sshd_idle_timeout_value: !!str 900
  tags:
    - always

- name: Set SSH Idle Timeout Interval
  block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)^\s*ClientAliveInterval\s+
        state: absent

    - name: Insert correct line to /etc/ssh/sshd_config
      lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        line: ClientAliveInterval {{ sshd_idle_timeout_value }}
        state: present
        insertbefore: ^[#\s]*Match
        validate: /usr/sbin/sshd -t -f %s
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz"]
  tags:
    - sshd_set_idle_timeout
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - CCE-80906-1
    - NIST-800-53-CM-6(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-SC-10
    - NIST-800-53-CM-6(a)
    - NIST-800-171-3.1.11
    - PCI-DSS-Req-8.1.8
    - CJIS-5.5.6


apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
spec:
  config:
    ignition:
      version: 2.2.0
    storage:
      files:
      - contents:
          source: data:,%23%09%24OpenBSD%3A%20sshd_config%2Cv%201.103%202018/04/09%2020%3A41%3A22%20tj%20Exp%20%24%0A%0A%23%20This%20is%20the%20sshd%20server%20system-wide%20configuration%20file.%20%20See%0A%23%20sshd_config%285%29%20for%20more%20information.%0A%0A%23%20This%20sshd%20was%20compiled%20with%20PATH%3D/usr/local/bin%3A/usr/bin%3A/usr/local/sbin%3A/usr/sbin%0A%0A%23%20The%20strategy%20used%20for%20options%20in%20the%20default%20sshd_config%20shipped%20with%0A%23%20OpenSSH%20is%20to%20specify%20options%20with%20their%20default%20value%20where%0A%23%20possible%2C%20but%20leave%20them%20commented.%20%20Uncommented%20options%20override%20the%0A%23%20default%20value.%0A%0A%23%20If%20you%20want%20to%20change%20the%20port%20on%20a%20SELinux%20system%2C%20you%20have%20to%20tell%0A%23%20SELinux%20about%20this%20change.%0A%23%20semanage%20port%20-a%20-t%20ssh_port_t%20-p%20tcp%20%23PORTNUMBER%0A%23%0A%23Port%2022%0A%23AddressFamily%20any%0A%23ListenAddress%200.0.0.0%0A%23ListenAddress%20%3A%3A%0A%0AHostKey%20/etc/ssh/ssh_host_rsa_key%0AHostKey%20/etc/ssh/ssh_host_ecdsa_key%0AHostKey%20/etc/ssh/ssh_host_ed25519_key%0A%0A%23%20Ciphers%20and%20keying%0ARekeyLimit%20512M%201h%0A%0A%23%20System-wide%20Crypto%20policy%3A%0A%23%20This%20system%20is%20following%20system-wide%20crypto%20policy.%20The%20changes%20to%0A%23%20Ciphers%2C%20MACs%2C%20KexAlgoritms%20and%20GSSAPIKexAlgorithsm%20will%20not%20have%20any%0A%23%20effect%20here.%20They%20will%20be%20overridden%20by%20command-line%20options%20passed%20on%0A%23%20the%20server%20start%20up.%0A%23%20To%20opt%20out%2C%20uncomment%20a%20line%20with%20redefinition%20of%20%20CRYPTO_POLICY%3D%0A%23%20variable%20in%20%20/etc/sysconfig/sshd%20%20to%20overwrite%20the%20policy.%0A%23%20For%20more%20information%2C%20see%20manual%20page%20for%20update-crypto-policies%288%29.%0A%0A%23%20Logging%0A%23SyslogFacility%20AUTH%0ASyslogFacility%20AUTHPRIV%0A%23LogLevel%20INFO%0A%0A%23%20Authentication%3A%0A%0A%23LoginGraceTime%202m%0APermitRootLogin%20no%0AStrictModes%20yes%0A%23MaxAuthTries%206%0A%23MaxSessions%2010%0A%0APubkeyAuthentication%20yes%0A%0A%23%20The%20default%20is%20to%20check%20both%20.ssh/authorized_keys%20and%20.ssh/authorized_keys2%0A%23%20but%20this%20is%20overridden%20so%20installations%20will%20only%20check%20.ssh/authorized_keys%0AAuthorizedKeysFile%09.ssh/authorized_keys%0A%0A%23AuthorizedPrincipalsFile%20none%0A%0A%23AuthorizedKeysCommand%20none%0A%23AuthorizedKeysCommandUser%20nobody%0A%0A%23%20For%20this%20to%20work%20you%20will%20also%20need%20host%20keys%20in%20/etc/ssh/ssh_known_hosts%0AHostbasedAuthentication%20no%0A%23%20Change%20to%20yes%20if%20you%20don%27t%20trust%20~/.ssh/known_hosts%20for%0A%23%20HostbasedAuthentication%0AIgnoreUserKnownHosts%20yes%0A%23%20Don%27t%20read%20the%20user%27s%20~/.rhosts%20and%20~/.shosts%20files%0AIgnoreRhosts%20yes%0A%0A%23%20To%20disable%20tunneled%20clear%20text%20passwords%2C%20change%20to%20no%20here%21%0A%23PasswordAuthentication%20yes%0APermitEmptyPasswords%20no%0APasswordAuthentication%20no%0A%0A%23%20Change%20to%20no%20to%20disable%20s/key%20passwords%0A%23ChallengeResponseAuthentication%20yes%0AChallengeResponseAuthentication%20no%0A%0A%23%20Kerberos%20options%0AKerberosAuthentication%20no%0A%23KerberosOrLocalPasswd%20yes%0A%23KerberosTicketCleanup%20yes%0A%23KerberosGetAFSToken%20no%0A%23KerberosUseKuserok%20yes%0A%0A%23%20GSSAPI%20options%0AGSSAPIAuthentication%20no%0AGSSAPICleanupCredentials%20no%0A%23GSSAPIStrictAcceptorCheck%20yes%0A%23GSSAPIKeyExchange%20no%0A%23GSSAPIEnablek5users%20no%0A%0A%23%20Set%20this%20to%20%27yes%27%20to%20enable%20PAM%20authentication%2C%20account%20processing%2C%0A%23%20and%20session%20processing.%20If%20this%20is%20enabled%2C%20PAM%20authentication%20will%0A%23%20be%20allowed%20through%20the%20ChallengeResponseAuthentication%20and%0A%23%20PasswordAuthentication.%20%20Depending%20on%20your%20PAM%20configuration%2C%0A%23%20PAM%20authentication%20via%20ChallengeResponseAuthentication%20may%20bypass%0A%23%20the%20setting%20of%20%22PermitRootLogin%20without-password%22.%0A%23%20If%20you%20just%20want%20the%20PAM%20account%20and%20session%20checks%20to%20run%20without%0A%23%20PAM%20authentication%2C%20then%20enable%20this%20but%20set%20PasswordAuthentication%0A%23%20and%20ChallengeResponseAuthentication%20to%20%27no%27.%0A%23%20WARNING%3A%20%27UsePAM%20no%27%20is%20not%20supported%20in%20Fedora%20and%20may%20cause%20several%0A%23%20problems.%0AUsePAM%20yes%0A%0A%23AllowAgentForwarding%20yes%0A%23AllowTcpForwarding%20yes%0A%23GatewayPorts%20no%0AX11Forwarding%20yes%0A%23X11DisplayOffset%2010%0A%23X11UseLocalhost%20yes%0A%23PermitTTY%20yes%0A%0A%23%20It%20is%20recommended%20to%20use%20pam_motd%20in%20/etc/pam.d/sshd%20instead%20of%20PrintMotd%2C%0A%23%20as%20it%20is%20more%20configurable%20and%20versatile%20than%20the%20built-in%20version.%0APrintMotd%20no%0A%0APrintLastLog%20yes%0A%23TCPKeepAlive%20yes%0APermitUserEnvironment%20no%0ACompression%20no%0AClientAliveInterval%20600%0AClientAliveCountMax%200%0A%23UseDNS%20no%0A%23PidFile%20/var/run/sshd.pid%0A%23MaxStartups%2010%3A30%3A100%0A%23PermitTunnel%20no%0A%23ChrootDirectory%20none%0A%23VersionAddendum%20none%0A%0A%23%20no%20default%20banner%20path%0ABanner%20/etc/issue%0A%0A%23%20Accept%20locale-related%20environment%20variables%0AAcceptEnv%20LANG%20LC_CTYPE%20LC_NUMERIC%20LC_TIME%20LC_COLLATE%20LC_MONETARY%20LC_MESSAGES%0AAcceptEnv%20LC_PAPER%20LC_NAME%20LC_ADDRESS%20LC_TELEPHONE%20LC_MEASUREMENT%0AAcceptEnv%20LC_IDENTIFICATION%20LC_ALL%20LANGUAGE%0AAcceptEnv%20XMODIFIERS%0A%0A%23%20override%20default%20of%20no%20subsystems%0ASubsystem%09sftp%09/usr/libexec/openssh/sftp-server%0A%0A%23%20Example%20of%20overriding%20settings%20on%20a%20per-user%20basis%0A%23Match%20User%20anoncvs%0A%23%09X11Forwarding%20no%0A%23%09AllowTcpForwarding%20no%0A%23%09PermitTTY%20no%0A%23%09ForceCommand%20cvs%20server%0A%0A%23Log%20user%20connections%0ALogLevel%20VERBOSE%0A%0AUsePrivilegeSeparation%20sandbox
        filesystem: root
        mode: 0600
        path: /etc/ssh/sshd_config
OVAL test results details

Verify if Profile set Value sshd_required as not required  oval:ssg-test_sshd_not_required:tst:1  false

Following items have been found on the system:
Var refValue
oval:ssg-sshd_required:var:10

Verify if Value of sshd_required is the default  oval:ssg-test_sshd_requirement_unset:tst:1  true

Following items have been found on the system:
Var refValue
oval:ssg-sshd_required:var:10

package openssh-server is removed  oval:ssg-test_package_openssh-server_removed:tst:1  false

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
openssh-serverx86_64(none)5.el88.0p10:8.0p1-5.el8199e2f91fd431d51openssh-server-0:8.0p1-5.el8.x86_64

Verify if Profile set Value sshd_required as required  oval:ssg-test_sshd_required:tst:1  false

Following items have been found on the system:
Var refValue
oval:ssg-sshd_required:var:10

Verify if Value of sshd_required is the default  oval:ssg-test_sshd_requirement_unset:tst:1  true

Following items have been found on the system:
Var refValue
oval:ssg-sshd_required:var:10

package openssh-server is installed  oval:ssg-test_package_openssh-server_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
openssh-serverx86_64(none)5.el88.0p10:8.0p1-5.el8199e2f91fd431d51openssh-server-0:8.0p1-5.el8.x86_64

timeout is configured  oval:ssg-test_sshd_idle_timeout:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_sshd_idle_timeout:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/ssh/sshd_config^[\s]*(?i)ClientAliveInterval[\s]+(\d+)[\s]*(?:#.*)?$1
Enable Smartcards in SSSDxccdf_org.ssgproject.content_rule_sssd_enable_smartcards mediumCCE-80909-5

Enable Smartcards in SSSD

Rule IDxccdf_org.ssgproject.content_rule_sssd_enable_smartcards
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-sssd_enable_smartcards:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80909-5

References:  CCI-001954, SRG-OS-000375-GPOS-00160, SRG-OS-000107-VMM-000530

Description

SSSD should be configured to authenticate access to the system using smart cards. To enable smart cards in SSSD, set pam_cert_auth to true under the [pam] section in /etc/sssd/sssd.conf. For example:

[pam]
pam_cert_auth = true

Rationale

Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.

OVAL test results details

package sssd-common is removed  oval:ssg-test_service_sssd_package_sssd-common_removed:tst:1  false

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
sssd-commonx86_64(none)9.el82.3.00:2.3.0-9.el8199e2f91fd431d51sssd-common-0:2.3.0-9.el8.x86_64

Test that the sssd service is not running  oval:ssg-test_service_not_running_sssd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
sssd.serviceActiveStateactive

Test that the property LoadState from the service sssd is masked  oval:ssg-test_service_loadstate_is_masked_sssd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
sssd.serviceLoadStateloaded

Test that the property FragmentPath from the service sssd is set to /dev/null  oval:ssg-test_service_fragmentpath_is_dev_null_sssd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
sssd.serviceFragmentPath/usr/lib/systemd/system/sssd.service

Testing if /etc/sssd/sssd.conf exists  oval:ssg-test_sssd_conf_exists:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_sssd_conf_exists:obj:1 of type file_object
Filepath
/etc/sssd/sssd.conf

tests the value of pam_cert_auth setting in the /etc/sssd/sssd.conf file  oval:ssg-test_sssd_enable_smartcards:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_sssd_enable_smartcards:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/sssd/sssd.conf^[\s]*\[pam](?:[^\n\[]*\n+)+?[\s]*pam_cert_auth[\s]*=[\s]*true$1
Enable the NTP Daemonxccdf_org.ssgproject.content_rule_service_chronyd_or_ntpd_enabled mediumCCE-80874-1

Enable the NTP Daemon

Rule IDxccdf_org.ssgproject.content_rule_service_chronyd_or_ntpd_enabled
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-service_chronyd_or_ntpd_enabled:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80874-1

References:  2.2.1.1, 1, 14, 15, 16, 3, 5, 6, APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01, 3.3.7, CCI-000160, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, CM-6(a), AU-8(1)(a), PR.PT-1, Req-10.4, SRG-OS-000356-VMM-001340

Description

Run the following command to determine the current status of the chronyd service:

$ systemctl is-active chronyd
If the service is running, it should return the following:
active
Note: The chronyd daemon is enabled by default.

Run the following command to determine the current status of the ntpd service:
$ systemctl is-active ntpd
If the service is running, it should return the following:
active
Note: The ntpd daemon is not enabled by default. Though as mentioned in the previous sections in certain environments the ntpd daemon might be preferred to be used rather than the chronyd one. Refer to: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/ch-Configuring_NTP_Using_the_chrony_Suite.html for guidance which NTP daemon to choose depending on the environment used.

Rationale

Enabling some of chronyd or ntpd services ensures that the NTP daemon will be running and that the system will synchronize its time to any servers specified. This is important whether the system is configured to be a client (and synchronize only its own clock) or it is also acting as an NTP server to other systems. Synchronizing time is essential for authentication services such as Kerberos, but it is also important for maintaining accurate logs and auditing possible security breaches.

The chronyd and ntpd NTP daemons offer all of the functionality of ntpdate, which is now deprecated. Additional information on this is available at http://support.ntp.org/bin/view/Dev/DeprecatingNtpdate

OVAL test results details

package chrony is installed  oval:ssg-test_service_chronyd_package_chrony_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
chronyx86_64(none)1.el83.50:3.5-1.el8199e2f91fd431d51chrony-0:3.5-1.el8.x86_64

Test that the chronyd service is running  oval:ssg-test_service_running_chronyd:tst:1  true

Following items have been found on the system:
UnitPropertyValue
chronyd.serviceActiveStateactive

systemd test  oval:ssg-test_multi_user_wants_chronyd:tst:1  true

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_chronyd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

package ntp is installed  oval:ssg-test_service_ntpd_package_ntp_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_service_ntpd_package_ntp_installed:obj:1 of type rpminfo_object
Name
ntp

Test that the ntpd service is running  oval:ssg-test_service_running_ntpd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
ntpd.serviceActiveStateinactive

systemd test  oval:ssg-test_multi_user_wants_ntpd:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_ntpd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service
Specify a Remote NTP Serverxccdf_org.ssgproject.content_rule_chronyd_or_ntpd_specify_remote_server mediumCCE-80765-1

Specify a Remote NTP Server

Rule IDxccdf_org.ssgproject.content_rule_chronyd_or_ntpd_specify_remote_server
Result
pass
Multi-check ruleno
OVAL Definition IDoval:ssg-chronyd_or_ntpd_specify_remote_server:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80765-1

References:  2.2.1.2, 1, 14, 15, 16, 3, 5, 6, APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01, 3.3.7, CCI-000160, CCI-001891, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, CM-6(a), AU-8(1)(a), AU-8(2), PR.PT-1, Req-10.4.1, Req-10.4.3, SRG-OS-000355-VMM-001330

Description

Depending on specific functional requirements of a concrete production environment, the Red Hat Enterprise Linux 8 system can be configured to utilize the services of the chronyd NTP daemon (the default), or services of the ntpd NTP daemon. Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/ch-Configuring_NTP_Using_the_chrony_Suite.html for more detailed comparison of the features of both of the choices, and for further guidance how to choose between the two NTP daemons.
To specify a remote NTP server for time synchronization, perform the following:

  • if the system is configured to use the chronyd as the NTP daemon (the default), edit the file /etc/chrony.conf as follows,
  • if the system is configured to use the ntpd as the NTP daemon, edit the file /etc/ntp.conf as documented below.
Add or correct the following lines, substituting the IP or hostname of a remote NTP server for ntpserver:
server ntpserver
This instructs the NTP software to contact that remote server to obtain time data.

Rationale

Synchronizing with an NTP server makes it possible to collate system logs from multiple sources or correlate computer events with real time events.

OVAL test results details

package chrony is installed  oval:ssg-test_service_chronyd_package_chrony_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
chronyx86_64(none)1.el83.50:3.5-1.el8199e2f91fd431d51chrony-0:3.5-1.el8.x86_64

Test that the chronyd service is running  oval:ssg-test_service_running_chronyd:tst:1  true

Following items have been found on the system:
UnitPropertyValue
chronyd.serviceActiveStateactive

systemd test  oval:ssg-test_multi_user_wants_chronyd:tst:1  true

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_chronyd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

Ensure at least one NTP server is set  oval:ssg-test_chronyd_remote_server:tst:1  true

Following items have been found on the system:
PathContent
/etc/chrony.confpool 2.rhel.pool.ntp.org iburst

package ntp is installed  oval:ssg-test_service_ntpd_package_ntp_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_service_ntpd_package_ntp_installed:obj:1 of type rpminfo_object
Name
ntp

Test that the ntpd service is running  oval:ssg-test_service_running_ntpd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
ntpd.serviceActiveStateinactive

systemd test  oval:ssg-test_multi_user_wants_ntpd:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_ntpd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

Ensure at least one ntpd NTP server is set  oval:ssg-test_ntp_remote_server:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_ntp_remote_server:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/ntp.conf^[\s]*server[\s]+.+$1
Specify Additional Remote NTP Serversxccdf_org.ssgproject.content_rule_chronyd_or_ntpd_specify_multiple_servers mediumCCE-80764-4

Specify Additional Remote NTP Servers

Rule IDxccdf_org.ssgproject.content_rule_chronyd_or_ntpd_specify_multiple_servers
Result
fail
Multi-check ruleno
OVAL Definition IDoval:ssg-chronyd_or_ntpd_specify_multiple_servers:def:1
Time2021-03-21T20:15:53+01:00
Severitymedium
Identifiers and References

Identifiers:  CCE-80764-4

References:  1, 14, 15, 16, 3, 5, 6, APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, CM-6(a), AU-8(1)(a), AU-8(2), PR.PT-1, Req-10.4.3

Description

Depending on specific functional requirements of a concrete production environment, the Red Hat Enterprise Linux 8 system can be configured to utilize the services of the chronyd NTP daemon (the default), or services of the ntpd NTP daemon. Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/ch-Configuring_NTP_Using_the_chrony_Suite.html for more detailed comparison of the features of both of the choices, and for further guidance how to choose between the two NTP daemons.
Additional NTP servers can be specified for time synchronization. To do so, perform the following:

  • if the system is configured to use the chronyd as the NTP daemon (the default), edit the file /etc/chrony.conf as follows,
  • if the system is configured to use the ntpd as the NTP daemon, edit the file /etc/ntp.conf as documented below.
Add additional lines of the following form, substituting the IP address or hostname of a remote NTP server for ntpserver:
server ntpserver

Rationale

Specifying additional NTP servers increases the availability of accurate time data, in the event that one of the specified servers becomes unavailable. This is typical for a system acting as an NTP server for other systems.



# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv -a ! -f /run/.containerenv ]; then


var_multiple_time_servers="0.rhel.pool.ntp.org,1.rhel.pool.ntp.org,2.rhel.pool.ntp.org,3.rhel.pool.ntp.org"

config_file="/etc/ntp.conf"
/usr/sbin/pidof ntpd || config_file="/etc/chrony.conf"

if ! [ "$(grep -c '^server' "$config_file")" -gt 1 ] ; then
  if ! grep -q '#[[:space:]]*server' "$config_file" ; then
    for server in $(echo "$var_multiple_time_servers" | tr ',' '\n') ; do
      printf '\nserver %s' "$server" >> "$config_file"
    done
  else
    sed -i 's/#[ \t]*server/server/g' "$config_file"
  fi
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
OVAL test results details

package chrony is installed  oval:ssg-test_service_chronyd_package_chrony_installed:tst:1  true

Following items have been found on the system:
NameArchEpochReleaseVersionEvrSignature keyidExtended name
chronyx86_64(none)1.el83.50:3.5-1.el8199e2f91fd431d51chrony-0:3.5-1.el8.x86_64

Test that the chronyd service is running  oval:ssg-test_service_running_chronyd:tst:1  true

Following items have been found on the system:
UnitPropertyValue
chronyd.serviceActiveStateactive

systemd test  oval:ssg-test_multi_user_wants_chronyd:tst:1  true

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_chronyd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

Ensure more than one chronyd NTP server is set  oval:ssg-test_chronyd_multiple_servers:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-object_chronyd_multiple_servers:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/chrony.conf^([\s]*server[\s]+.+$){2,}$1

package ntp is installed  oval:ssg-test_service_ntpd_package_ntp_installed:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_test_service_ntpd_package_ntp_installed:obj:1 of type rpminfo_object
Name
ntp

Test that the ntpd service is running  oval:ssg-test_service_running_ntpd:tst:1  false

Following items have been found on the system:
UnitPropertyValue
ntpd.serviceActiveStateinactive

systemd test  oval:ssg-test_multi_user_wants_ntpd:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

systemd test  oval:ssg-test_multi_user_wants_ntpd_socket:tst:1  false

Following items have been found on the system:
UnitDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependencyDependency
multi-user.targetbasic.targetsysinit.targetkmod-static-nodes.servicesystemd-tmpfiles-setup.serviceldconfig.servicesys-kernel-config.mountsystemd-update-utmp.serviceplymouth-read-write.servicesystemd-random-seed.servicesystemd-journal-catalog-update.servicedracut-shutdown.servicelocal-fs.target-.mountboot.mountsystemd-remount-fs.servicesystemd-modules-load.servicesystemd-udevd.servicelvm2-lvmpolld.socketsystemd-udev-trigger.servicecryptsetup.targetdev-hugepages.mountsys-fs-fuse-connections.mountrngd.serviceproc-sys-fs-binfmt_misc.automountsys-kernel-debug.mountselinux-autorelabel-mark.servicenis-domainname.servicesystemd-binfmt.servicesystemd-update-done.servicesystemd-journald.servicedev-mqueue.mountimport-state.servicesystemd-hwdb-update.servicesystemd-ask-password-console.pathsystemd-sysctl.servicesystemd-machine-id-commit.servicesystemd-sysusers.servicelvm2-monitor.servicesystemd-journal-flush.serviceloadmodules.serviceplymouth-start.serviceswap.targetdev-mapper-rhel\x2dswap.swapsystemd-firstboot.servicesystemd-tmpfiles-setup-dev.serviceslices.target-.slicesystem.slicetimers.targetsystemd-tmpfiles-clean.timerdnf-makecache.timerunbound-anchor.timermicrocode.servicesockets.targetcockpit.socketdm-event.socketsystemd-journald.socketsystemd-udevd-control.socketsystemd-initctl.socketsssd-kcm.socketsystemd-coredump.socketdbus.socketsystemd-udevd-kernel.socketsystemd-journald-dev-log.socketpaths.targetauditd.servicechronyd.servicehttpd.servicesystemd-update-utmp-runlevel.serviceplymouth-quit.serviceirqbalance.servicecrond.servicegetty.targetgetty@tty1.servicersyslog.servicesshd.serviceNetworkManager.servicesssd.servicefirewalld.serviceremote-fs.targetsystemd-ask-password-wall.pathplymouth-quit-wait.servicedbus.servicetuned.servicerhsmcertd.servicekdump.servicesystemd-logind.servicesystemd-user-sessions.service

Ensure more than one ntpd NTP server is set  oval:ssg-test_ntpd_multiple_servers:tst:1  false

No items have been found conforming to the following objects:
Object oval:ssg-obj_ntpd_multiple_servers:obj:1 of type textfilecontent54_object
FilepathPatternInstance
/etc/ntp.conf^([\s]*server[\s]+.+$){2,}$1
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.