| Group  
                Guide to the Secure Configuration of Oracle Linux 7
                          Group contains 46 groups and 93 rules | 
| Group  
                System Settings
                          Group contains 22 groups and 37 rules | 
| [ref]  
                        Contains rules that check correct system settings. | 
| Group  
                Installing and Maintaining Software
                          Group contains 6 groups and 12 rules | 
| [ref]  
                        The following sections contain information on
security-relevant choices during the initial operating system
installation process and the setup of software
updates. | 
| Group  
                System and Software Integrity
                          Group contains 2 groups and 3 rules | 
| [ref]  
                        System and software integrity can be gained by installing antivirus, increasing
system encryption strength with FIPS, verifying installed software, enabling SELinux,
installing an Intrusion Prevention System, etc. However, installing or enabling integrity
checking tools cannot prevent  intrusions, but they can detect that an intrusion
may have occurred. Requirements for integrity checking may be highly dependent on
the environment in which the system will be used. Snapshot-based approaches such
as AIDE may induce considerable overhead in the presence of frequent software updates. | 
| Group  
                Software Integrity Checking
                          Group contains 1 group and 3 rules | 
| [ref]  
                        Both the AIDE (Advanced Intrusion Detection Environment)
software and the RPM package management system provide
mechanisms for verifying the integrity of installed software.
AIDE uses snapshots of file metadata (such as hashes) and compares these
to current system files in order to detect changes.
         
The RPM package management system can conduct integrity
checks by comparing information in its metadata database with
files installed on the system. | 
| Group  
                Verify Integrity with RPM
                          Group contains 3 rules | 
| [ref]  
                        The RPM package management system includes the ability
to verify the integrity of installed packages by comparing the
installed files with information about the files taken from the
package metadata stored in the RPM database. Although an attacker
could corrupt the RPM database (analogous to attacking the AIDE
database as described above), this check can still reveal
modification of important files. To list which files on the system differ from what is expected by the RPM database:
 $ rpm -qVa 
See the man page for  rpm to see a complete explanation of each column. | 
| | Rule  
                                Verify File Hashes with RPM
                                  [ref] |  | 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 matches 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 --noconfig | grep '^..5' 
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
          Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of packages present on the system. It is not a
problem in most cases, but especially systems with a large number of installed packages
can be affected. |  | 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. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_rpm_verify_hashes |  | References: | | cis-csc | 11, 2, 3, 9 |  | cjis | 5.10.4.1 |  | cobit5 | APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02 |  | cui | 3.3.8, 3.4.1 |  | hipaa | 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4 |  | isa-62443-2013 | SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6 |  | iso27001-2013 | 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 |  | nist | CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3) |  | nist-csf | PR.DS-6, PR.DS-8, PR.IP-1 |  | pcidss | Req-11.5 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-010020 |  | ism | 1409 |  | pcidss4 | 11.5.2 |  | stigref | SV-221653r1015161_rule | 
 |  |  | 
 | 
| | Rule  
                                Verify and Correct Ownership with RPM
                                  [ref] |  | The RPM package management system can check file ownership permissions of installed software
packages, including many that are important to system security. After locating a file with
incorrect permissions, which can be found with:
 rpm -Va | awk '{ if (substr($0,6,1)=="U" || substr($0,7,1)=="G") print $NF }'
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 --restore PACKAGENAME
          Warning: 
                                        Profiles may require that specific files be owned by root while the default owner defined
by the vendor is different. Such files will be reported as a finding and need to be
evaluated according to your policy and deployment environment.Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of packages present on the system. It is not a
problem in most cases, but especially systems with a large number of installed packages
can be affected. |  | Rationale: | Ownership of binaries and configuration files that is incorrect could allow an unauthorized
user to gain privileges that they should not have. The ownership set by the vendor should be
maintained. Any deviations from this baseline should be investigated. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_rpm_verify_ownership |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 3, 5, 6, 9 |  | cjis | 5.10.4.1 |  | cobit5 | APO01.06, APO11.04, BAI03.05, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.07, DSS06.02, MEA02.01 |  | cui | 3.3.8, 3.4.1 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 7.6 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R4.2, CIP-003-8 R6, CIP-007-3 R4, CIP-007-3 R4.1, CIP-007-3 R4.2 |  | nist | CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3) |  | nist-csf | PR.AC-4, PR.DS-5, PR.IP-1, PR.PT-1 |  | pcidss | Req-11.5 |  | os-srg | SRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098, SRG-OS-000278-GPOS-00108 |  | stigid | OL07-00-010010 |  | ism | 1409 |  | pcidss4 | 11.5.2 |  | stigref | SV-221652r991557_rule | 
 |  |  | 
 | 
| | Rule  
                                Verify and Correct File Permissions with RPM
                                  [ref] |  | 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 --restore PACKAGENAME
          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.Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of packages present on the system. It is not a
problem in most cases, but especially systems with a large number of installed packages
can be affected. |  | 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. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_rpm_verify_permissions |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 3, 5, 6, 9 |  | cjis | 5.10.4.1 |  | cobit5 | APO01.06, APO11.04, BAI03.05, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.07, DSS06.02, MEA02.01 |  | cui | 3.3.8, 3.4.1 |  | hipaa | 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 7.6 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R4.2, CIP-003-8 R6, CIP-007-3 R4, CIP-007-3 R4.1, CIP-007-3 R4.2 |  | nist | CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3), CM-6(a) |  | nist-csf | PR.AC-4, PR.DS-5, PR.IP-1, PR.PT-1 |  | pcidss | Req-11.5 |  | os-srg | SRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098, SRG-OS-000258-GPOS-00099, SRG-OS-000278-GPOS-00108 |  | stigid | OL07-00-010010 |  | ism | 1409 |  | pcidss4 | 11.5.2 |  | stigref | SV-221652r991557_rule | 
 |  |  | 
 | 
| Group  
                Sudo
                          Group contains 3 rules | 
| [ref]  
                        Sudo, which stands for "su 'do'", provides the ability to delegate authority
to certain users, groups of users, or system administrators. When configured for system
users and/or groups,  Sudo can allow a user or group to execute privileged commands
that normally only  root is allowed to execute.
        
For more information on  Sudo and addition  Sudo configuration options, see
https://www.sudo.ws . | 
| | Rule  
                                Ensure Users Re-Authenticate for Privilege Escalation - sudo !authenticate
                                  [ref] |  | The sudo !authenticateoption, when specified, allows a user to execute commands using
sudo without having to authenticate. This should be disabled by making sure that the!authenticateoption does not exist in/etc/sudoersconfiguration file or
any sudo configuration snippets in/etc/sudoers.d/. |  | Rationale: | Without re-authentication, users may access resources or perform tasks for which they
do not have authorization.
 When operating systems provide the capability to escalate a functional capability, it
is critical that the user re-authenticate.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sudo_remove_no_authenticate |  | References: | | cis-csc | 1, 12, 15, 16, 5 |  | cobit5 | DSS05.04, DSS05.10, DSS06.03, DSS06.10 |  | isa-62443-2009 | 4.3.3.5.1, 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | A.18.1.4, 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 |  | nist | IA-11, CM-6(a) |  | nist-csf | PR.AC-1, PR.AC-7 |  | os-srg | SRG-OS-000373-GPOS-00156, SRG-OS-000373-GPOS-00157, SRG-OS-000373-GPOS-00158 |  | stigid | OL07-00-010350 |  | ism | 1546 |  | stigref | SV-228569r1015194_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure Users Re-Authenticate for Privilege Escalation - sudo NOPASSWD
                                  [ref] |  | The sudo NOPASSWDtag, when specified, allows a user to execute
commands using sudo without having to authenticate. This should be disabled
by making sure that theNOPASSWDtag does not exist in/etc/sudoersconfiguration file or any sudo configuration snippets
in/etc/sudoers.d/. |  | Rationale: | Without re-authentication, users may access resources or perform tasks for which they
do not have authorization.
 When operating systems provide the capability to escalate a functional capability, it
is critical that the user re-authenticate.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sudo_remove_nopasswd |  | References: | | cis-csc | 1, 12, 15, 16, 5 |  | cobit5 | DSS05.04, DSS05.10, DSS06.03, DSS06.10 |  | isa-62443-2009 | 4.3.3.5.1, 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | A.18.1.4, 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 |  | nist | IA-11, CM-6(a) |  | nist-csf | PR.AC-1, PR.AC-7 |  | os-srg | SRG-OS-000373-GPOS-00156, SRG-OS-000373-GPOS-00157, SRG-OS-000373-GPOS-00158 |  | stigid | OL07-00-010340 |  | ism | 1546 |  | stigref | SV-221692r1015185_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure Users Re-Authenticate for Privilege Escalation - sudo
                                  [ref] |  | The sudo NOPASSWDand!authenticateoption, when
specified, allows a user to execute commands using sudo without having to
authenticate. This should be disabled by making sure thatNOPASSWDand/or!authenticatedo not exist in/etc/sudoersconfiguration file or any sudo configuration snippets
in/etc/sudoers.d/." |  | Rationale: | Without re-authentication, users may access resources or perform tasks for which they
do not have authorization.
 When operating systems provide the capability to escalate a functional capability, it
is critical that the user re-authenticate.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sudo_require_authentication |  | References: | | cis-csc | 1, 12, 15, 16, 5 |  | cobit5 | DSS05.04, DSS05.10, DSS06.03, DSS06.10 |  | isa-62443-2009 | 4.3.3.5.1, 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | A.18.1.4, 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 |  | nist | IA-11, CM-6(a) |  | nist-csf | PR.AC-1, PR.AC-7 |  | os-srg | SRG-OS-000373-GPOS-00156 |  | ism | 1546 |  | pcidss4 | 2.2.6, 2.2 | 
 |  |  | 
 | 
| Group  
                System Tooling / Utilities
                          Group contains  1 rule | 
| [ref]  
                        The following checks evaluate the system for recommended base packages -- both for installation
and removal. | 
| | Rule  
                                Install rear Package
                                  [ref] |  | The  rear package can be installed with the following command:
 
$ sudo yum install rear |  | Rationale: | rearcontains the Relax-and-Recover (ReaR) utility. ReaR produces a bootable
image of a system and restores from backup using this image.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_rear_installed |  | References: |  |  |  | 
 | 
| Group  
                Updating Software
                          Group contains 5 rules | 
| [ref]  
                        The  yum command line tool is used to install and
update software packages. The system also provides a graphical
software update tool in the System  menu, in the Administration  submenu,
called Software Update .
        
Oracle Linux 7 systems contain an installed software catalog called
the RPM database, which records metadata of installed packages. Consistently using
 yum or the graphical Software Update  for all software installation
allows for insight into the current inventory of installed software on the system.
       
       | 
| | Rule  
                                Ensure gpgcheck Enabled In Main yum Configuration
                                  [ref] |  | The  gpgcheck option controls whether
RPM packages' signatures are always checked prior to installation.
To configure yum to check package signatures before installing
them, ensure the following line appears in  /etc/yum.conf in
the  [main] section:
 gpgcheck=1 |  | Rationale: | Changes to any software components can have significant effects on the
overall security of the operating system. This requirement ensures the
software has not been tampered with and that it has been provided by a
trusted vendor.
Accordingly, patches, service packs, device drivers, or operating system
components must be signed with a certificate recognized and approved by the
organization.
 Verifying the authenticity of the software prior to installation
validates the integrity of the patch or upgrade received from a vendor.
This ensures the software has not been tampered with and that it has been
provided by a trusted vendor. Self-signed certificates are disallowed by
this requirement. Certificates used to verify the software must be from an
approved Certificate Authority (CA).
 |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated |  | References: | | cis-csc | 11, 2, 3, 9 |  | cjis | 5.10.4.1 |  | cobit5 | APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02 |  | cui | 3.4.8 |  | hipaa | 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4 |  | isa-62443-2013 | SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6 |  | iso27001-2013 | 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 |  | nist | CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), SA-12, SA-12(10), CM-11(a), CM-11(b) |  | nist-csf | PR.DS-6, PR.DS-8, PR.IP-1 |  | ospp | FPT_TUD_EXT.1, FPT_TUD_EXT.2 |  | pcidss | Req-6.2 |  | os-srg | SRG-OS-000366-GPOS-00153 |  | stigid | OL07-00-020050 |  | anssi | R59 |  | ism | 1493 |  | pcidss4 | 6.3.3, 6.3 |  | stigref | SV-221710r1015187_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure gpgcheck Enabled for Local Packages
                                  [ref] |  | yumshould be configured to verify the signature(s) of local packages
prior to installation. To configureyumto verify signatures of local
packages, set thelocalpkg_gpgcheckto1in/etc/yum.conf.
 |  | Rationale: | Changes to any software components can have significant effects to the overall security
of the operating system. This requirement ensures the software has not been tampered and
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.
 |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_ensure_gpgcheck_local_packages |  | References: | | cis-csc | 11, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.4.8 |  | hipaa | 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nist | CM-11(a), CM-11(b), CM-6(a), CM-5(3), SA-12, SA-12(10) |  | nist-csf | PR.IP-1 |  | ospp | FPT_TUD_EXT.1, FPT_TUD_EXT.2 |  | os-srg | SRG-OS-000366-GPOS-00153 |  | stigid | OL07-00-020060 |  | anssi | R59 |  | ism | 1493 |  | stigref | SV-221711r1015188_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure gpgcheck Enabled for All yum Package Repositories
                                  [ref] |  | 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)." |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled |  | References: | | cis-csc | 11, 2, 3, 9 |  | cjis | 5.10.4.1 |  | cobit5 | APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02 |  | cui | 3.4.8 |  | hipaa | 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4 |  | isa-62443-2013 | SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6 |  | iso27001-2013 | 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 |  | nist | CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), SA-12, SA-12(10), CM-11(a), CM-11(b) |  | nist-csf | PR.DS-6, PR.DS-8, PR.IP-1 |  | ospp | FPT_TUD_EXT.1, FPT_TUD_EXT.2 |  | pcidss | Req-6.2 |  | os-srg | SRG-OS-000366-GPOS-00153 |  | anssi | R59 |  | ism | 1493 |  | pcidss4 | 6.3.3, 6.3 | 
 |  |  | 
 | 
| | Rule  
                                Ensure Oracle Linux GPG Key Installed
                                  [ref] |  | To ensure the system can cryptographically verify base software
packages come from Oracle (and to connect to the Unbreakable Linux Network to
receive them), the Oracle GPG key must properly be installed.
To install the Oracle GPG key, run:
 $ sudo uln_register 
If the system is not connected to the Internet,
then install the Oracle GPG key from trusted media such as
the Oracle installation CD-ROM or DVD. Assuming the disc is mounted
in  /media/cdrom, use the following command as the root user to import
it into the keyring:
 $ sudo rpm --import /media/cdrom/RPM-GPG-KEY-oracle 
Alternatively, the key may be pre-loaded during the Oracle installation. In
such cases, the key can be installed by running the following command:
 sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-oracle |  | Rationale: | Changes to software components can have significant effects on the
overall security of the operating system. This requirement ensures
the software has not been tampered with and that it has been provided
by a trusted vendor. The Oracle GPG key is necessary to
cryptographically verify packages are from Oracle. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_ensure_oracle_gpgkey_installed |  | References: | | cis-csc | 11, 2, 3, 9 |  | cobit5 | APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02 |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4 |  | isa-62443-2013 | SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6 |  | iso27001-2013 | 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 |  | nist | CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), CM-11(a), CM-11(b) |  | nist-csf | PR.DS-6, PR.DS-8, PR.IP-1 |  | pcidss | Req-6.2 |  | stigid | OL07-00-010019 |  | cis | 1.2.2 |  | anssi | R59 |  | stigref | SV-256975r1015198_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure Software Patches Installed
                                  [ref] |  | 
If the system is joined to the ULN
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 ULN and installed using  rpm.
         
NOTE: U.S. Defense systems are required to be patched within 30 days or sooner as local policy
dictates.Warning: 
                                        The OVAL feed of Oracle Linux 7 is not a XML file, which may not be understood by all scanners. |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_security_patches_up_to_date |  | References: | | cis-csc | 18, 20, 4 |  | cjis | 5.10.4.1 |  | cobit5 | APO12.01, APO12.02, APO12.03, APO12.04, BAI03.10, DSS05.01, DSS05.02 |  | isa-62443-2009 | 4.2.3, 4.2.3.12, 4.2.3.7, 4.2.3.9 |  | iso27001-2013 | A.12.6.1, A.14.2.3, A.16.1.3, A.18.2.2, A.18.2.3 |  | nist | SI-2(5), SI-2(c), CM-6(a) |  | nist-csf | ID.RA-1, PR.IP-12 |  | ospp | FMT_MOF_EXT.1 |  | pcidss | Req-6.2 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-020260 |  | anssi | R61 |  | ism | 1409 |  | pcidss4 | 6.3.3, 6.3 |  | stigref | SV-221720r991589_rule | 
 |  |  | 
 | 
| Group  
                Account and Access Control
                          Group contains 3 groups and 2 rules | 
| [ref]  
                        In traditional Unix security, if an attacker gains
shell access to a certain login account, they can perform any action
or access any file to which that account has access. Therefore,
making it more difficult for unauthorized people to gain shell
access to accounts, particularly to privileged accounts, is a
necessary part of securing a system. This section introduces
mechanisms for restricting access to accounts under
Oracle Linux 7. | 
| Group  
                Protect Accounts by Restricting Password-Based Login
                          Group contains 2 groups and 2 rules | 
| [ref]  
                        Conventionally, Unix shell accounts are accessed by
providing a username and password to a login program, which tests
these values for correctness using the  /etc/passwd and
 /etc/shadow files. Password-based login is vulnerable to
guessing of weak passwords, and to sniffing and man-in-the-middle
attacks against passwords entered over a network or at an insecure
console. Therefore, mechanisms for accessing accounts by entering
usernames and passwords should be restricted to those which are
operationally necessary. | 
| Group  
                Verify Proper Storage and Existence of Password
Hashes
                          Group contains  1 rule | 
| [ref]  
                        By default, password hashes for local accounts are stored
in the second field (colon-separated) in
 /etc/shadow. This file should be readable only by
processes running with root credentials, preventing users from
casually accessing others' password hashes and attempting
to crack them.
However, it remains possible to misconfigure the system
and store password hashes
in world-readable files such as  /etc/passwd, or
to even store passwords themselves in plaintext on the system.
Using system-provided tools for password change/creation
should allow administrators to avoid such misconfiguration. | 
| | Rule  
                                Prevent Login to Accounts With Empty Password
                                  [ref] |  | 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
nullokin/etc/pam.d/system-authand/etc/pam.d/password-authto prevent logins with empty passwords. Warning: 
                                        If the system relies on authselecttool to manage PAM settings, the remediation
will also useauthselecttool. However, if any manual modification was made in
PAM files, theauthselectintegrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report.
Note that this rule is not applicable for systems running within a
container. Having user with empty password within a container is not
considered a risk, because it should not be possible to directly login into
a container anyway. |  | 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. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_no_empty_passwords |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 18, 3, 5 |  | cjis | 5.5.2 |  | cobit5 | APO01.06, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.10 |  | cui | 3.1.1, 3.1.5 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | IA-5(1)(a), IA-5(c), CM-6(a) |  | nist-csf | PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5 |  | ospp | FIA_UAU.1 |  | pcidss | Req-8.2.3 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-010290 |  | ism | 1546 |  | pcidss4 | 8.3.1, 8.3 |  | stigref | SV-221687r991589_rule | 
 |  |  | 
 | 
| Group  
                Restrict Root Logins
                          Group contains  1 rule | 
| [ref]  
                        Direct root logins should be allowed only for emergency use.
In normal situations, the administrator should access the system
via a unique unprivileged account, and then use  su or  sudo to execute
privileged commands. Discouraging administrators from accessing the
root account directly ensures an audit trail in organizations with
multiple administrators. Locking down the channels through which
root can connect directly also reduces opportunities for
password-guessing against the root account. The  login program
uses the file  /etc/securetty to determine which interfaces
should allow root logins.
The virtual devices  /dev/console
and  /dev/tty* represent the system consoles (accessible via
the Ctrl-Alt-F1 through Ctrl-Alt-F6 keyboard sequences on a default
installation). The default securetty file also contains  /dev/vc/*.
These are likely to be deprecated in most environments, but may be retained
for compatibility. Root should also be prohibited from connecting
via network protocols. Other sections of this document
include guidance describing how to prevent root from logging in via SSH. | 
| | Rule  
                                Verify Only Root Has UID 0
                                  [ref] |  | If any account other than root has a UID of 0, this misconfiguration should
be investigated and the accounts other than root should be removed or have
their UID changed.
If the account is associated with system commands or applications the UID
should be changed to one greater than "0" but less than "1000."
Otherwise assign a UID greater than "1000" that has not already been
assigned.
 |  | Rationale: | An account has root authority if it has a UID of 0. Multiple accounts
with a UID of 0 afford more opportunity for potential intruders to
guess a password for a privileged account. Proper configuration of
sudo is recommended to afford multiple system administrators
access to root privileges in an accountable manner. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_accounts_no_uid_except_zero |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.10 |  | cui | 3.1.1, 3.1.5 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.2.3, CIP-004-6 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3 |  | nist | IA-2, AC-6(5), IA-4(b) |  | nist-csf | PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5 |  | pcidss | Req-8.5 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-020310 |  | ism | 1546 |  | pcidss4 | 8.2.1, 8.2 |  | stigref | SV-221723r991589_rule | 
 |  |  | 
 | 
| Group  
                Configure Syslog
                          Group contains 2 rules | 
| [ref]  
                        The syslog service has been the default Unix logging mechanism for
many years. It has a number of downsides, including inconsistent log format,
lack of authentication for received messages, and lack of authentication,
encryption, or reliable transport for messages sent over a network. However,
due to its long history, syslog is a de facto standard which is supported by
almost all Unix applications.
       
In Oracle Linux 7, rsyslog has replaced ksyslogd as the
syslog daemon of choice, and it includes some additional security features
such as reliable, connection-oriented (i.e. TCP) transmission of logs, the
option to log to database formats, and the encryption of log data en route to
a central logging server.
This section discusses how to configure rsyslog for
best effect, and how to use tools provided with the system to maintain and
monitor logs. | 
| | Rule  
                                Ensure rsyslog is Installed
                                  [ref] |  | Rsyslog is installed by default. The  rsyslog package can be installed with the following command:   $ sudo yum install rsyslog |  | Rationale: | The rsyslog package provides the rsyslog daemon, which provides
system logging services. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_rsyslog_installed |  | References: | | cis-csc | 1, 14, 15, 16, 3, 5, 6 |  | cobit5 | APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01 |  | hipaa | 164.312(a)(2)(ii) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1 |  | nist | CM-6(a) |  | nist-csf | PR.PT-1 |  | os-srg | SRG-OS-000479-GPOS-00224, SRG-OS-000051-GPOS-00024, SRG-OS-000480-GPOS-00227 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Enable rsyslog Service
                                  [ref] |  | The  rsyslog service provides syslog-style logging by default on Oracle Linux 7.
The  rsyslog service can be enabled with the following command:
 $ sudo systemctl enable rsyslog.service |  | Rationale: | The rsyslogservice must be running in order to provide
logging services, which are essential to system administration. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_rsyslog_enabled |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | hipaa | 164.312(a)(2)(ii) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2, SR 7.1, SR 7.2 |  | iso27001-2013 | 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.14.2.7, A.15.2.1, A.15.2.2, A.17.2.1 |  | nist | CM-6(a), AU-4(1) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.DS-4, PR.PT-1 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | ism | 1409 | 
 |  |  | 
 | 
| Group  
                Network Configuration and Firewalls
                          Group contains 2 groups and 3 rules | 
| [ref]  
                        Most systems must be connected to a network of some
sort, and this brings with it the substantial risk of network
attack. This section discusses the security impact of decisions
about networking which must be made when configuring a system.
       
This section also discusses firewalls, network access
controls, and other network security frameworks, which allow
system-level rules to be written that can limit an attackers' ability
to connect to your system. These rules can specify that network
traffic should be allowed or denied from certain IP addresses,
hosts, and networks. The rules can also specify which of the
system's network services are available to particular hosts or
networks. | 
| Group  
                firewalld
                          Group contains 1 group and 2 rules | 
| [ref]  
                        The dynamic firewall daemon  firewalld provides a
dynamically managed firewall with support for network “zones” to assign
a level of trust to a network and its associated connections and interfaces.
It has support for IPv4 and IPv6 firewall settings. It supports Ethernet
bridges and has a separation of runtime and permanent configuration options.
It also has an interface for services or applications to add firewall rules
directly.
 
A graphical configuration tool,  firewall-config, is used to configure
 firewalld, which in turn uses  iptables tool to communicate
with  Netfilter in the kernel which implements packet filtering.
 
The firewall service provided by  firewalld is dynamic rather than
static because changes to the configuration can be made at anytime and are
immediately implemented. There is no need to save or apply the changes. No
unintended disruption of existing network connections occurs as no part of
the firewall has to be reloaded. | 
| Group  
                Inspect and Activate Default firewalld Rules
                          Group contains 2 rules | 
| [ref]  
                        Firewalls can be used to separate networks into different zones
based on the level of trust the user has decided to place on the devices and
traffic within that network.  NetworkManager informs firewalld to which
zone an interface belongs. An interface's assigned zone can be changed by
 NetworkManager or via the  firewall-config tool.
 
The zone settings in  /etc/firewalld/ are a range of preset settings
which can be quickly applied to a network interface. These are the zones
provided by firewalld sorted according to the default trust level of the
zones from untrusted to trusted:
 drop
 Any incoming network packets are dropped, there is no
reply. Only outgoing network connections are possible.block
 Any incoming network connections are rejected with an
icmp-host-prohibitedmessage for IPv4 andicmp6-adm-prohibitedfor IPv6. Only network connections initiated from within the system are
possible.public
 For use in public areas. You do not trust the other
computers on the network to not harm your computer. Only selected incoming
connections are accepted.external
 For use on external networks with masquerading enabled
especially for routers. You do not trust the other computers on the network to
not harm your computer. Only selected incoming connections are accepted.dmz
 For computers in your demilitarized zone that are
publicly-accessible with limited access to your internal network. Only selected
incoming connections are accepted.work
 For use in work areas. You mostly trust the other computers
on networks to not harm your computer. Only selected incoming connections are
accepted.home
 For use in home areas. You mostly trust the other computers
on networks to not harm your computer. Only selected incoming connections are
accepted.internal
 For use on internal networks. You mostly trust the
other computers on the networks to not harm your computer. Only selected
incoming connections are accepted.trusted
 All network connections are accepted.
 
It is possible to designate one of these zones to be the default zone. When
interface connections are added to  NetworkManager, they are assigned
to the default zone. On installation, the default zone in firewalld is set to
be the public zone.
 
To find out all the settings of a zone, for example the  public zone,
enter the following command as root:
 # firewall-cmd --zone=public --list-all 
Example output of this command might look like the following:
 
# firewall-cmd --zone=public --list-all
public
  interfaces:
  services: mdns dhcpv6-client ssh
  ports:
  forward-ports:
  icmp-blocks: source-quench
 
To view the network zones currently active, enter the following command as root:
 # firewall-cmd --get-service 
The following listing displays the result of this command
on common Oracle Linux 7 system:
 
# firewall-cmd --get-service
amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp
high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd
ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn
pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind
samba samba-client smtp ssh telnet tftp tftp-client transmission-client
vnc-server wbem-https
 
Finally to view the network zones that will be active after the next firewalld
service reload, enter the following command as root:
 # firewall-cmd --get-service --permanent | 
| | Rule  
                                Install firewalld Package
                                  [ref] |  | The  firewalld package can be installed with the following command:
 
$ sudo yum install firewalld |  | Rationale: | "Firewalld" provides an easy and effective way to block/limit remote access to the system via ports, services, and protocols.
Remote access services, such as those providing remote access to network devices and information systems, which lack automated control capabilities, increase risk and make remote user access management difficult at best.
Remote access is access to nonpublic information systems by an authorized user (or an information system) communicating through an external, non-organization-controlled network. Remote access methods include, for example, dial-up, broadband, and wireless.
Oracle Linux 7 functionality (e.g., SSH) must be capable of taking enforcement action if the audit reveals unauthorized activity.
Automated control of remote access sessions allows organizations to ensure ongoing compliance with remote access policies by enforcing connection rules of remote access applications on a variety of information system components (e.g., servers, workstations, notebook computers, smartphones, and tablets)." |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_firewalld_installed |  | References: | | nist | CM-6(a) |  | ospp | FMT_SMF_EXT.1 |  | os-srg | SRG-OS-000096-GPOS-00050, SRG-OS-000297-GPOS-00115, SRG-OS-000298-GPOS-00116, SRG-OS-000480-GPOS-00227, SRG-OS-000480-GPOS-00232 |  | stigid | OL07-00-040520 |  | ism | 1409 |  | pcidss4 | 1.2.1, 1.2 |  | stigref | SV-221868r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Verify firewalld Enabled
                                  [ref] |  | 
The  firewalld service can be enabled with the following command:
 $ sudo systemctl enable firewalld.service |  | Rationale: | Access control methods provide the ability to enhance system security posture
by restricting services and known good IP addresses and address ranges. This
prevents connections from unknown hosts and protocols. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_firewalld_enabled |  | References: | | cis-csc | 11, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.1.3, 3.4.7 |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nerc-cip | CIP-003-8 R4, CIP-003-8 R5, CIP-004-6 R3 |  | nist | AC-4, CM-7(b), CA-3(5), SC-7(21), CM-6(a) |  | nist-csf | PR.IP-1 |  | ospp | FMT_SMF_EXT.1 |  | os-srg | SRG-OS-000096-GPOS-00050, SRG-OS-000297-GPOS-00115, SRG-OS-000480-GPOS-00227, SRG-OS-000480-GPOS-00231, SRG-OS-000480-GPOS-00232 |  | stigid | OL07-00-040520 |  | bsi | SYS.1.6.A5, SYS.1.6.A21 |  | ism | 1409 |  | pcidss4 | 1.2.1, 1.2 |  | stigref | SV-221868r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure System is Not Acting as a Network Sniffer
                                  [ref] |  | The system should not be acting as a network sniffer, which can
capture all traffic on the network to which it is connected. Run the following
to determine if any interface is running in promiscuous mode:
 $ ip link | grep PROMISC 
Promiscuous mode of an interface can be disabled with the following command:
 $ sudo ip link set dev device_namemulticast off promisc off |  | Rationale: | Network interfaces in promiscuous mode allow for the capture of all network traffic
visible to the system. If unauthorized individuals can access these applications, it
may allow them to collect information such as logon IDs, passwords, and key exchanges
between systems.
 If the system is being used to perform a network troubleshooting function, the use of these
tools must be documented with the Information Systems Security Manager (ISSM) and restricted
to only authorized personnel.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_network_sniffer_disabled |  | References: | | cis-csc | 1, 11, 14, 3, 9 |  | cobit5 | APO11.06, APO12.06, BAI03.10, BAI09.01, BAI09.02, BAI09.03, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.05, DSS04.05, DSS05.02, DSS05.05, DSS06.06 |  | isa-62443-2009 | 4.2.3.4, 4.3.3.3.7, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, 4.4.3.4 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6, SR 7.8 |  | iso27001-2013 | A.11.1.2, A.11.2.4, A.11.2.5, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.16.1.6, A.8.1.1, A.8.1.2, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a), CM-7(2), MA-3 |  | nist-csf | DE.DP-5, ID.AM-1, PR.IP-1, PR.MA-1, PR.PT-3 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040670 |  | ism | 1409 |  | pcidss4 | 1.4.5, 1.4 |  | stigref | SV-221882r991589_rule | 
 |  |  | 
 | 
| Group  
                File Permissions and Masks
                          Group contains 5 groups and 16 rules | 
| [ref]  
                        Traditional Unix security relies heavily on file and
directory permissions to prevent unauthorized users from reading or
modifying files to which they should not have access.
       
Several of the commands in this section search filesystems
for files or directories with certain characteristics, and are
intended to be run on every local partition on a given system.
When the variable PART  appears in one of the commands below,
it means that the command is intended to be run repeatedly, with the
name of each local partition substituted for PART  in turn.
       
The following command prints a list of all xfs partitions on the local
system, which is the default filesystem for Oracle Linux 7
installations:
 $ mount -t xfs | awk '{print $3}'
For any systems that use a different
local filesystem type, modify this command as appropriate. | 
| Group  
                Verify Permissions on Important Files and
Directories
                          Group contains 1 group and 8 rules | 
| [ref]  
                        Permissions for many files on a system must be set
restrictively to ensure sensitive information is properly protected.
This section discusses important
permission restrictions which can be verified
to ensure that no harmful discrepancies have
arisen. | 
| Group  
                Verify File Permissions Within Some Important Directories
                          Group contains 4 rules | 
| [ref]  
                        Some directories contain files whose confidentiality or integrity
is notably important and may also be susceptible to misconfiguration over time, particularly if
unpackaged software is installed. As such,
an argument exists to verify that files' permissions within these directories remain
configured correctly and restrictively. | 
| | Rule  
                                Verify that System Executables Have Root Ownership
                                  [ref] |  | System executables are stored in the following directories by default:
 /bin
/sbin
/usr/bin
/usr/libexec
/usr/local/bin
/usr/local/sbin
/usr/sbin 
All files in these directories should be owned by the  root user.
If any file FILE  in these directories is found
to be owned by a user other than root, correct its ownership with the
following command:
 $ sudo chown root FILE
          |  | Rationale: | System binaries are executed by privileged users as well as system services,
and restrictive permissions are necessary to ensure that their
execution of these programs cannot be co-opted. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_ownership_binary_dirs |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-5(6), CM-5(6).1, CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000259-GPOS-00100 |  | anssi | R50 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Verify that Shared Library Files Have Root Ownership
                                  [ref] |  | System-wide shared library files, which are linked to executables
during process load time or run time, are stored in the following directories
by default:
 /lib
/lib64
/usr/lib
/usr/lib64
 
Kernel modules, which can be added to the kernel during runtime, are also
stored in  /lib/modules. All files in these directories should be
owned by the  root user. If the directory, or any file in these
directories, is found to be owned by a user other than root correct its
ownership with the following command:
 $ sudo chown root FILE
          |  | Rationale: | Files from shared library directories are loaded into the address
space of processes (including privileged ones) or of the kernel itself at
runtime. Proper ownership is necessary to protect the integrity of the system. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_ownership_library_dirs |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-5(6), CM-5(6).1, CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000259-GPOS-00100 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Verify that System Executables Have Restrictive Permissions
                                  [ref] |  | System executables are stored in the following directories by default:
 /bin
/sbin
/usr/bin
/usr/libexec
/usr/local/bin
/usr/local/sbin
/usr/sbin 
All files in these directories should not be group-writable or world-writable.
If any file FILE  in these directories is found
to be group-writable or world-writable, correct its permission with the
following command:
 $ sudo chmod go-w FILE
          |  | Rationale: | System binaries are executed by privileged users, as well as system services,
and restrictive permissions are necessary to ensure execution of these programs
cannot be co-opted. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_permissions_binary_dirs |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-5(6), CM-5(6).1, CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000259-GPOS-00100 |  | anssi | R50 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Verify that Shared Library Files Have Restrictive Permissions
                                  [ref] |  | System-wide shared library files, which are linked to executables
during process load time or run time, are stored in the following directories
by default:
 /lib
/lib64
/usr/lib
/usr/lib64
 
Kernel modules, which can be added to the kernel during runtime, are
stored in  /lib/modules. All files in these directories
should not be group-writable or world-writable. If any file in these
directories is found to be group-writable or world-writable, correct
its permission with the following command:
 $ sudo chmod go-w FILE
          |  | Rationale: | Files from shared library directories are loaded into the address
space of processes (including privileged ones) or of the kernel itself at
runtime. Restrictive permissions are necessary to protect the integrity of the system. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_permissions_library_dirs |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-6(a), CM-5(6), CM-5(6).1, AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000259-GPOS-00100 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Verify that All World-Writable Directories Have Sticky Bits Set
                                  [ref] |  | When the so-called 'sticky bit' is set on a directory, only the owner of a given file may
remove that file from the directory. Without the sticky bit, any user with write access to a
directory may remove any file in the directory. Setting the sticky bit prevents users from
removing each other's files. In cases where there is no reason for a directory to be
world-writable, a better solution is to remove that permission rather than to set the sticky
bit. However, if a directory is used by a particular application, consult that application's
documentation instead of blindly changing modes.
 
To set the sticky bit on a world-writable directory DIR , run the following command:
 $ sudo chmod +t DIR
        Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of directories present on the system. It is
not a problem in most cases, but especially systems with a large number of directories can
be affected. See https://access.redhat.com/articles/6999111.Warning: 
                                        Please note that there might be cases where the rule remediation cannot fix directory permissions.
This can happen for example when running on a system with some immutable parts.
These immutable parts cannot be remediated because they are read-only.
Example of such directories can be OStree deployments located at /sysroot/ostree/deploy.
In such case, it is needed to make modifications to the underlying ostree snapshot and this is out of scope of regular rule remediation. |  | Rationale: | Failing to set the sticky bit on public directories allows unauthorized users to delete files
in the directory structure.
 The only authorized public directories are those temporary directories supplied with the
system, or those designed to be temporary file repositories. The setting is normally reserved
for directories used by the system, by users for temporary file storage (such as
 /tmp),
and for directories requiring global read/write access. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_dir_perms_world_writable_sticky_bits |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000138-GPOS-00069 |  | anssi | R54 |  | ism | 1409 |  | pcidss4 | 2.2.6, 2.2 | 
 |  |  | 
 | 
| | Rule  
                                Ensure All SGID Executables Are Authorized
                                  [ref] |  | The SGID (set group id) bit should be set only on files that were installed via authorized
means. A straightforward means of identifying unauthorized SGID files is determine if any were
not installed as part of an RPM package, which is cryptographically verified. Investigate the
origin of any unpackaged SGID files. This configuration check considers authorized SGID files
those which were installed via RPM. It is assumed that when an individual has sudo access to
install an RPM and all packages are signed with an organizationally-recognized GPG key, the
software should be considered an approved package on the system. Any SGID file not deployed
through an RPM will be flagged for further review. Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111. |  | Rationale: | Executable files with the SGID permission run with the privileges of the owner of the file.
SGID files of uncertain provenance could allow for unprivileged users to elevate privileges.
The presence of these files should be strictly controlled on the system. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_permissions_unauthorized_sgid |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nist | CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | anssi | R56 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Ensure All SUID Executables Are Authorized
                                  [ref] |  | The SUID (set user id) bit should be set only on files that were installed via authorized
means. A straightforward means of identifying unauthorized SUID files is determine if any were
not installed as part of an RPM package, which is cryptographically verified. Investigate the
origin of any unpackaged SUID files. This configuration check considers authorized SUID files
those which were installed via RPM. It is assumed that when an individual has sudo access to
install an RPM and all packages are signed with an organizationally-recognized GPG key, the
software should be considered an approved package on the system. Any SUID file not deployed
through an RPM will be flagged for further review. Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111. |  | Rationale: | Executable files with the SUID permission run with the privileges of the owner of the file.
SUID files of uncertain provenance could allow for unprivileged users to elevate privileges.
The presence of these files should be strictly controlled on the system. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_permissions_unauthorized_suid |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nist | CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | anssi | R56 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Ensure No World-Writable Files Exist
                                  [ref] |  | It is generally a good idea to remove global (other) write access to a file when it is
discovered. However, check with documentation for specific applications before making changes.
Also, monitor for recurring world-writable files, as these may be symptoms of a misconfigured
application or user account. Finally, this applies to real files and not virtual files that
are a part of pseudo file systems such as sysfsorprocfs. Warning: 
                                        This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111. |  | Rationale: | Data in world-writable files can be modified by any user on the system. In almost all
circumstances, files can be configured using a combination of user and group permissions to
support whatever legitimate access is needed without the risk caused by world-writable files. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_file_permissions_unauthorized_world_writable |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-6(a), AC-6(1) |  | nist-csf | PR.AC-4, PR.DS-5 |  | anssi | R54 |  | ism | 1409 |  | pcidss4 | 2.2.6, 2.2 | 
 |  |  | 
 | 
| Group  
                Restrict Partition Mount Options
                          Group contains 3 rules | 
| [ref]  
                        System partitions can be mounted with certain options
that limit what files on those partitions can do. These options
are set in the  /etc/fstab configuration file, and can be
used to make certain types of malicious behavior more difficult. | 
| | Rule  
                                Add nodev Option to /dev/shm
                                  [ref] |  | The nodevmount option can be used to prevent creation of device
files in/dev/shm. Legitimate character and block devices should
not exist within temporary directories like/dev/shm.
Add thenodevoption to the fourth column of/etc/fstabfor the line which controls mounting of/dev/shm. |  | Rationale: | The only legitimate location for device files is the /devdirectory
located on the root partition. The only exception to this is chroot jails. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_mount_option_dev_shm_nodev |  | References: | | cis-csc | 11, 13, 14, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS05.06, DSS06.06 |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6 |  | iso27001-2013 | A.11.2.9, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.8.2.1, A.8.2.2, A.8.2.3, A.8.3.1, A.8.3.3, A.9.1.2 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a), AC-6, AC-6(1), MP-7 |  | nist-csf | PR.IP-1, PR.PT-2, PR.PT-3 |  | os-srg | SRG-OS-000368-GPOS-00154 |  | stigid | OL07-00-021024 |  | ism | 1409 |  | stigref | SV-221747r958804_rule | 
 |  |  | 
 | 
| | Rule  
                                Add noexec Option to /dev/shm
                                  [ref] |  | The noexecmount option can be used to prevent binaries
from being executed out of/dev/shm.
It can be dangerous to allow the execution of binaries
from world-writable temporary storage directories such as/dev/shm.
Add thenoexecoption to the fourth column of/etc/fstabfor the line which controls mounting of/dev/shm. |  | Rationale: | Allowing users to execute binaries from world-writable directories
such as /dev/shmcan expose the system to potential compromise. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_mount_option_dev_shm_noexec |  | References: | | cis-csc | 11, 13, 14, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS05.06, DSS06.06 |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6 |  | iso27001-2013 | A.11.2.9, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.8.2.1, A.8.2.2, A.8.2.3, A.8.3.1, A.8.3.3, A.9.1.2 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a), AC-6, AC-6(1), MP-7 |  | nist-csf | PR.IP-1, PR.PT-2, PR.PT-3 |  | os-srg | SRG-OS-000368-GPOS-00154 |  | stigid | OL07-00-021024 |  | ism | 1409 |  | stigref | SV-221747r958804_rule | 
 |  |  | 
 | 
| | Rule  
                                Add nosuid Option to /dev/shm
                                  [ref] |  | The nosuidmount option can be used to prevent execution
of setuid programs in/dev/shm.  The SUID and SGID permissions should not
be required in these world-writable directories.
Add thenosuidoption to the fourth column of/etc/fstabfor the line which controls mounting of/dev/shm. |  | Rationale: | The presence of SUID and SGID executables should be tightly controlled. Users
should not be able to execute SUID or SGID binaries from temporary storage partitions. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_mount_option_dev_shm_nosuid |  | References: | | cis-csc | 11, 13, 14, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS05.06, DSS06.06 |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6 |  | iso27001-2013 | A.11.2.9, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.8.2.1, A.8.2.2, A.8.2.3, A.8.3.1, A.8.3.3, A.9.1.2 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a), AC-6, AC-6(1), MP-7 |  | nist-csf | PR.IP-1, PR.PT-2, PR.PT-3 |  | os-srg | SRG-OS-000368-GPOS-00154 |  | stigid | OL07-00-021024 |  | ism | 1409 |  | stigref | SV-221747r958804_rule | 
 |  |  | 
 | 
| Group  
                Restrict Programs from Dangerous Execution Patterns
                          Group contains 1 group and 5 rules | 
| [ref]  
                        The recommendations in this section are designed to
ensure that the system's features to protect against potentially
dangerous program execution are activated.
These protections are applied at the system initialization or
kernel level, and defend against certain types of badly-configured
or compromised programs. | 
| Group  
                Enable ExecShield
                          Group contains 2 rules | 
| [ref]  
                        ExecShield describes kernel features that provide
protection against exploitation of memory corruption errors such as buffer
overflows. These features include random placement of the stack and other
memory regions, prevention of execution in memory that should only hold data,
and special handling of text buffers. These protections are enabled by default
on 32-bit systems and controlled through  sysctl variables 
 kernel.exec-shield and  kernel.randomize_va_space. On the latest
64-bit systems,  kernel.exec-shield cannot be enabled or disabled with 
 sysctl. | 
| | Rule  
                                Restrict Exposed Kernel Pointer Addresses Access
                                  [ref] |  | To set the runtime status of the  kernel.kptr_restrict kernel parameter, run the following command:  $ sudo sysctl -w kernel.kptr_restrict=1
         
To make sure that the setting is persistent, add the following line to a file in the directory  /etc/sysctl.d:  kernel.kptr_restrict = 1
          |  | Rationale: | Exposing kernel pointers (through procfs or seq_printf()) exposes kernel
writeable structures which may contain functions pointers. If a write vulnerability
occurs in the kernel, allowing write access to any of this structure, the kernel can
be compromised. This option disallow any program without the CAP_SYSLOG capability
to get the addresses of kernel pointers by replacing them with 0. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sysctl_kernel_kptr_restrict |  | References: | | nerc-cip | CIP-002-5 R1.1, CIP-002-5 R1.2, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 4.1, CIP-004-6 4.2, CIP-004-6 R2.2.3, CIP-004-6 R2.2.4, CIP-004-6 R2.3, CIP-004-6 R4, CIP-005-6 R1, CIP-005-6 R1.1, CIP-005-6 R1.2, CIP-007-3 R3, CIP-007-3 R3.1, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3, CIP-007-3 R8.4, CIP-009-6 R.1.1, CIP-009-6 R4 |  | nist | SC-30, SC-30(2), SC-30(5), CM-6(a) |  | ospp | FMT_SMF_EXT.1 |  | os-srg | SRG-OS-000132-GPOS-00067, SRG-OS-000433-GPOS-00192, SRG-OS-000480-GPOS-00227 |  | anssi | R9 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Enable Randomized Layout of Virtual Address Space
                                  [ref] |  | To set the runtime status of the  kernel.randomize_va_space kernel parameter, run the following command:  $ sudo sysctl -w kernel.randomize_va_space=2 
To make sure that the setting is persistent, add the following line to a file in the directory  /etc/sysctl.d:  kernel.randomize_va_space = 2 |  | Rationale: | Address space layout randomization (ASLR) makes it more difficult for an
attacker to predict the location of attack code they have introduced into a
process's address space during an attempt at exploitation. Additionally,
ASLR makes it more difficult for an attacker to know the location of
existing code in order to re-purpose it using return oriented programming
(ROP) techniques. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sysctl_kernel_randomize_va_space |  | References: | | cui | 3.1.7 |  | hipaa | 164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e) |  | nerc-cip | CIP-002-5 R1.1, CIP-002-5 R1.2, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 4.1, CIP-004-6 4.2, CIP-004-6 R2.2.3, CIP-004-6 R2.2.4, CIP-004-6 R2.3, CIP-004-6 R4, CIP-005-6 R1, CIP-005-6 R1.1, CIP-005-6 R1.2, CIP-007-3 R3, CIP-007-3 R3.1, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3, CIP-007-3 R8.4, CIP-009-6 R.1.1, CIP-009-6 R4 |  | nist | SC-30, SC-30(2), CM-6(a) |  | pcidss | Req-2.2.1 |  | os-srg | SRG-OS-000433-GPOS-00193, SRG-OS-000480-GPOS-00227 |  | app-srg-ctr | SRG-APP-000450-CTR-001105 |  | stigid | OL07-00-040201 |  | anssi | R9 |  | ism | 1409 |  | pcidss4 | 3.3.1.1, 3.3.1, 3.3 |  | stigref | SV-221846r958928_rule | 
 |  |  | 
 | 
| | Rule  
                                Restrict Access to Kernel Message Buffer
                                  [ref] |  | To set the runtime status of the  kernel.dmesg_restrict kernel parameter, run the following command:  $ sudo sysctl -w kernel.dmesg_restrict=1 
To make sure that the setting is persistent, add the following line to a file in the directory  /etc/sysctl.d:  kernel.dmesg_restrict = 1 |  | Rationale: | Unprivileged access to the kernel syslog can expose sensitive kernel
address information. |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_sysctl_kernel_dmesg_restrict |  | References: | | cui | 3.1.5 |  | hipaa | 164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e) |  | nist | SI-11(a), SI-11(b) |  | ospp | FMT_SMF_EXT.1 |  | os-srg | SRG-OS-000132-GPOS-00067, SRG-OS-000138-GPOS-00069 |  | app-srg-ctr | SRG-APP-000243-CTR-000600 |  | stigid | OL07-00-010375 |  | anssi | R9 |  | ism | 1546 |  | stigref | SV-255901r958524_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable Kernel Image Loading
                                  [ref] |  | To set the runtime status of the  kernel.kexec_load_disabled kernel parameter, run the following command:  $ sudo sysctl -w kernel.kexec_load_disabled=1 
To make sure that the setting is persistent, add the following line to a file in the directory  /etc/sysctl.d:  kernel.kexec_load_disabled = 1 |  | Rationale: | Disabling kexec_load allows greater control of the kernel memory.
It makes it impossible to load another kernel image after it has been disabled.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sysctl_kernel_kexec_load_disabled |  | References: | | nist | CM-6 |  | ospp | FMT_SMF_EXT.1 |  | os-srg | SRG-OS-000480-GPOS-00227, SRG-OS-000366-GPOS-00153 |  | ism | 1409 | 
 |  |  | 
 | 
| | Rule  
                                Restrict usage of ptrace to descendant processes
                                  [ref] |  | To set the runtime status of the  kernel.yama.ptrace_scope kernel parameter, run the following command:  $ sudo sysctl -w kernel.yama.ptrace_scope=1 
To make sure that the setting is persistent, add the following line to a file in the directory  /etc/sysctl.d:  kernel.yama.ptrace_scope = 1 |  | Rationale: | Unrestricted usage of ptrace allows compromised binaries to run ptrace
on another processes of the user. Like this, the attacker can steal
sensitive information from the target processes (e.g. SSH sessions, web browser, ...)
without any additional assistance from the user (i.e. without resorting to phishing).
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sysctl_kernel_yama_ptrace_scope |  | References: |  |  |  | 
 | 
| Group  
                SELinux
                          Group contains 2 rules | 
| [ref]  
                        SELinux is a feature of the Linux kernel which can be
used to guard against misconfigured or compromised programs.
SELinux enforces the idea that programs should be limited in what
files they can access and what actions they can take.
       
The default SELinux policy, as configured on Oracle Linux 7, has been
sufficiently developed and debugged that it should be usable on
almost any system with minimal configuration and a small
amount of system administrator training. This policy prevents
system services - including most of the common network-visible
services such as mail servers, FTP servers, and DNS servers - from
accessing files which those services have no valid reason to
access. This action alone prevents a huge amount of possible damage
from network attacks against services, from trojaned software, and
so forth.
       
This guide recommends that SELinux be enabled using the
default (targeted) policy on every Oracle Linux 7 system, unless that
system has unusual requirements which make a stronger policy
appropriate.
For more information on SELinux, see https://docs.oracle.com/en/operating-systems/oracle-linux/selinux/ . | 
| | Rule  
                                Configure SELinux Policy
                                  [ref] |  | The SELinux  targeted policy is appropriate for
general-purpose desktops and servers, as well as systems in many other roles.
To configure the system to use this policy, add or correct the following line
in  /etc/selinux/config:
 SELINUXTYPE=targeted
       
Other policies, such as  mls, provide additional security labeling
and greater confinement but are not compatible with many general-purpose
use cases. |  | Rationale: | Setting the SELinux policy to  targeted or a more specialized policy
ensures the system will confine processes that are likely to be
targeted for exploitation, such as network or system services.
        
Note: During the development or debugging of SELinux modules, it is common to
temporarily place non-production systems in  permissive mode. In such
temporary cases, SELinux policies should be developed, and once work
is completed, the system should be reconfigured to
 targeted. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_selinux_policytype |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 3, 4, 5, 6, 8, 9 |  | cobit5 | APO01.06, APO11.04, APO13.01, BAI03.05, DSS01.05, DSS03.01, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.02, DSS06.03, DSS06.06, MEA02.01 |  | cui | 3.1.2, 3.7.2 |  | hipaa | 164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e) |  | isa-62443-2009 | 4.2.3.4, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.4, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, 4.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 7.1, SR 7.6 |  | iso27001-2013 | A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.1, A.12.1.2, 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.2, A.13.1.3, A.13.2.1, A.13.2.2, 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.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.2, CIP-003-8 R5.3, CIP-004-6 R2.2.3, CIP-004-6 R2.3, CIP-004-6 R3.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, CIP-007-3 R6.5 |  | nist | AC-3, AC-3(3)(a), AU-9, SC-7(21) |  | nist-csf | DE.AE-1, ID.AM-3, PR.AC-4, PR.AC-5, PR.AC-6, PR.DS-5, PR.PT-1, PR.PT-3, PR.PT-4 |  | ospp | FMT_MOF_EXT.1 |  | os-srg | SRG-OS-000445-GPOS-00199 |  | app-srg-ctr | SRG-APP-000233-CTR-000585 |  | stigid | OL07-00-020220 |  | anssi | R46, R64 |  | bsi | APP.4.4.A4, SYS.1.6.A3, SYS.1.6.A18, SYS.1.6.A21 |  | ism | 1409 |  | pcidss4 | 1.2.6, 1.2 |  | stigref | SV-228570r958944_rule | 
 |  |  | 
 | 
| | Rule  
                                Ensure SELinux State is Enforcing
                                  [ref] |  | The SELinux state should be set to  enforcing at
system boot time.  In the file  /etc/selinux/config, add or correct the
following line to configure the system to boot into enforcing mode:
 SELINUX=enforcing
       
Ensure that all files have correct SELinux labels by running:
 fixfiles onboot 
Then reboot the system. |  | Rationale: | Setting the SELinux state to enforcing ensures SELinux is able to confine
potentially compromised processes to the security policy, which is designed to
prevent them from causing damage to the system or further elevating their
privileges. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_selinux_state |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 3, 4, 5, 6, 8, 9 |  | cobit5 | APO01.06, APO11.04, APO13.01, BAI03.05, DSS01.05, DSS03.01, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.02, DSS06.03, DSS06.06, MEA02.01 |  | cui | 3.1.2, 3.7.2 |  | hipaa | 164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e) |  | isa-62443-2009 | 4.2.3.4, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.4, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, 4.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 7.1, SR 7.6 |  | iso27001-2013 | A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.1, A.12.1.2, 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.2, A.13.1.3, A.13.2.1, A.13.2.2, 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.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.2, CIP-003-8 R5.3, CIP-004-6 R2.2.3, CIP-004-6 R2.3, CIP-004-6 R3.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, CIP-007-3 R6.5 |  | nist | AC-3, AC-3(3)(a), AU-9, SC-7(21) |  | nist-csf | DE.AE-1, ID.AM-3, PR.AC-4, PR.AC-5, PR.AC-6, PR.DS-5, PR.PT-1, PR.PT-3, PR.PT-4 |  | ospp | FMT_MOF_EXT.1 |  | os-srg | SRG-OS-000445-GPOS-00199, SRG-OS-000134-GPOS-00068 |  | stigid | OL07-00-020210 |  | anssi | R37, R79 |  | bsi | APP.4.4.A4, SYS.1.6.A3, SYS.1.6.A18, SYS.1.6.A21 |  | ism | 1409 |  | pcidss4 | 1.2.6, 1.2 |  | stigref | SV-221716r958944_rule | 
 |  |  | 
 | 
| Group  
                Services
                          Group contains 14 groups and 28 rules | 
| [ref]  
                        The best protection against vulnerable software is running less software. This section describes how to review
the software which Oracle Linux 7 installs on a system and disable software which is not needed. It
then enumerates the software packages installed on a default Oracle Linux 7 system and provides guidance about which
ones can be safely disabled.
      
Oracle Linux 7 provides a convenient minimal install option that essentially installs the bare necessities for a functional
system. When building Oracle Linux 7 systems, it is highly recommended to select the minimal packages and then build up
the system from there. | 
| Group  
                Avahi Server
                          Group contains  1 group and 1 rule | 
| [ref]  
                        The Avahi daemon implements the DNS Service Discovery
and Multicast DNS protocols, which provide service and host
discovery on a network. It allows a system to automatically
identify resources on the network, such as printers or web servers.
This capability is also known as mDNSresponder and is a major part
of Zeroconf networking. | 
| Group  
                Disable Avahi Server if Possible
                          Group contains  1 rule | 
| [ref]  
                        Because the Avahi daemon service keeps an open network
port, it is subject to network attacks.
Disabling it can reduce the system's vulnerability to such attacks. | 
| | Rule  
                                Disable Avahi Server Software
                                  [ref] |  | 
The  avahi-daemon service can be disabled with the following command:
 $ sudo systemctl mask --now avahi-daemon.service |  | Rationale: | Because the Avahi daemon service keeps an open network
port, it is subject to network attacks. Its functionality
is convenient but is only appropriate if the local network
can be trusted. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_avahi-daemon_disabled |  | References: | | cis-csc | 11, 14, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS06.06 |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.IP-1, PR.PT-3 |  | ism | 1409 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| Group  
                Obsolete Services
                          Group contains 5 groups and 10 rules | 
| [ref]  
                        This section discusses a number of network-visible
services which have historically caused problems for system
security, and for which disabling or severely limiting the service
has been the best available guidance for some time. As a result of
this, many of these services are not installed as part of Oracle Linux 7
by default.
       
Organizations which are running these services should
switch to more secure equivalents as soon as possible.
If it remains absolutely necessary to run one of
these services for legacy reasons, care should be taken to restrict
the service as much as possible, for instance by configuring host
firewall software such as  iptables to restrict access to the
vulnerable service to only those remote hosts which have a known
need to use it. | 
| Group  
                Xinetd
                          Group contains 2 rules | 
| [ref]  
                        The  xinetd service acts as a dedicated listener for some
network services (mostly, obsolete ones) and can be used to provide access
controls and perform some logging. It has been largely obsoleted by other
features, and it is not installed by default. The older Inetd service
is not even available as part of Oracle Linux 7. | 
| | Rule  
                                Uninstall xinetd Package
                                  [ref] |  | The  xinetd package can be removed with the following command:
 
$ sudo yum erase xinetd |  | Rationale: | Removing the xinetdpackage decreases the risk of the
xinetd service's accidental (or intentional) activation. |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_xinetd_removed |  | References: | | cis-csc | 11, 12, 14, 15, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 |  | iso27001-2013 | A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4 |  | anssi | R62 |  | ism | 1409 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| | Rule  
                                Disable xinetd Service
                                  [ref] |  | 
The  xinetd service can be disabled with the following command:
 $ sudo systemctl mask --now xinetd.service |  | Rationale: | The xinetd service provides a dedicated listener service for some programs,
which is no longer necessary for commonly-used network services. Disabling
it ensures that these uncommon services are not running, and also prevents
attacks against xinetd itself. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_xinetd_disabled |  | References: | | cis-csc | 11, 12, 14, 15, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06 |  | cui | 3.4.7 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 |  | iso27001-2013 | A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4 |  | ism | 1409 | 
 |  |  | 
 | 
| Group  
                NIS
                          Group contains  1 rule | 
| [ref]  
                        The Network Information Service (NIS), also known as 'Yellow
Pages' (YP), and its successor NIS+ have been made obsolete by
Kerberos, LDAP, and other modern centralized authentication
services. NIS should not be used because it suffers from security
problems inherent in its design, such as inadequate protection of
important authentication information. | 
| | Rule  
                                Remove NIS Client
                                  [ref] |  | The Network Information Service (NIS), formerly known as Yellow Pages,
is a client-server directory service protocol used to distribute system configuration
files. The NIS client (ypbind) was used to bind a system to an NIS server
and receive the distributed configuration files. |  | Rationale: | The NIS service is inherently an insecure system that has been vulnerable
to DOS attacks, buffer overflows and has poor authentication for querying
NIS maps. NIS generally has been replaced by such protocols as Lightweight
Directory Access Protocol (LDAP). It is recommended that the service be
removed. |  | Severity: | unknown |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_ypbind_removed |  | References: | | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | anssi | R62 |  | ism | 1409 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| Group  
                Rlogin, Rsh, and Rexec
                          Group contains 2 rules | 
| [ref]  
                        The Berkeley r-commands are legacy services which
allow cleartext remote access and have an insecure trust
model. | 
| | Rule  
                                Uninstall rsh-server Package
                                  [ref] |  | The  rsh-server package can be removed with the following command:
 
$ sudo yum erase rsh-server |  | Rationale: | The rsh-serverservice provides unencrypted remote access service which does not
provide for the confidentiality and integrity of user passwords or the remote session and has very weak
authentication. If a privileged user were to login using this service, the privileged user password
could be compromised. Thersh-serverpackage provides several obsolete and insecure
network services. Removing it decreases the risk of those services' accidental (or intentional)
activation. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_rsh-server_removed |  | References: | | cis-csc | 11, 12, 14, 15, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 |  | iso27001-2013 | A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a), IA-5(1)(c) |  | nist-csf | PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4 |  | os-srg | SRG-OS-000095-GPOS-00049 |  | stigid | OL07-00-020000 |  | anssi | R62 |  | pcidss4 | 2.2.4, 2.2 |  | stigref | SV-221704r958478_rule | 
 |  |  | 
 | 
| | Rule  
                                Uninstall rsh Package
                                  [ref] |  | 
The rshpackage contains the client commands
for the rsh services |  | Rationale: | These legacy clients contain numerous security exposures and have
been replaced with the more secure SSH package. Even if the server is removed,
it is best to ensure the clients are also removed to prevent users from
inadvertently attempting to use these commands and therefore exposing
their credentials. Note that removing the rshpackage removes
the clients forrsh,rcp, andrlogin. |  | Severity: | unknown |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_rsh_removed |  | References: | | cui | 3.1.13 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | iso27001-2013 | A.8.2.3, A.13.1.1, A.13.2.1, A.13.2.3, A.14.1.2, A.14.1.3 |  | anssi | R62 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| Group  
                Chat/Messaging Services
                          Group contains 2 rules | 
| [ref]  
                        The talk software makes it possible for users to send and receive messages
across systems through a terminal session. | 
| | Rule  
                                Uninstall talk-server Package
                                  [ref] |  | The  talk-server package can be removed with the following command:   $ sudo yum erase talk-server |  | Rationale: | The talk software presents a security risk as it uses unencrypted protocols
for communications. Removing the talk-serverpackage decreases the
risk of the accidental (or intentional) activation of talk services. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_talk-server_removed |  | References: | | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | anssi | R62 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| | Rule  
                                Uninstall talk Package
                                  [ref] |  | The  talk package contains the client program for the
Internet talk protocol, which allows the user to chat with other users on
different systems. Talk is a communication program which copies lines from one
terminal to the terminal of another user.
The  talk package can be removed with the following command:
 
$ sudo yum erase talk |  | Rationale: | The talk software presents a security risk as it uses unencrypted protocols
for communications. Removing the talkpackage decreases the
risk of the accidental (or intentional) activation of talk client program. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_talk_removed |  | References: | | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | anssi | R62 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| Group  
                Telnet
                          Group contains 3 rules | 
| [ref]  
                        The telnet protocol does not provide confidentiality or integrity
for information transmitted on the network. This includes authentication
information such as passwords. Organizations which use telnet should be
actively working to migrate to a more secure protocol. | 
| | Rule  
                                Uninstall telnet-server Package
                                  [ref] |  | The  telnet-server package can be removed with the following command:
 
$ sudo yum erase telnet-server |  | Rationale: | It is detrimental for operating systems to provide, or install by default,
functionality exceeding requirements or mission objectives. These
unnecessary capabilities are often overlooked and therefore may remain
insecure. They increase the risk to the platform by providing additional
attack vectors.
The telnet service provides an unencrypted remote access service which does
not provide for the confidentiality and integrity of user passwords or the
remote session. If a privileged user were to login using this service, the
privileged user password could be compromised.
 Removing the
 telnet-serverpackage decreases the risk of the
telnet service's accidental (or intentional) activation. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_telnet-server_removed |  | References: | | cis-csc | 11, 12, 14, 15, 3, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 |  | iso27001-2013 | A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4 |  | pcidss | Req-2.2.2 |  | os-srg | SRG-OS-000095-GPOS-00049 |  | stigid | OL07-00-021710 |  | anssi | R62 |  | ism | 1409 |  | pcidss4 | 2.2.4, 2.2 |  | stigref | SV-221763r958478_rule | 
 |  |  | 
 | 
| | Rule  
                                Remove telnet Clients
                                  [ref] |  | The telnet client allows users to start connections to other systems via
the telnet protocol. |  | Rationale: | The telnetprotocol is insecure and unencrypted. The use
of an unencrypted transmission medium could allow an unauthorized user
to steal credentials. Thesshpackage provides an
encrypted session and stronger security and is included in Oracle Linux 7. |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_telnet_removed |  | References: | | cui | 3.1.13 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | iso27001-2013 | A.8.2.3, A.13.1.1, A.13.2.1, A.13.2.3, A.14.1.2, A.14.1.3 |  | anssi | R62 |  | ism | 1409 |  | pcidss4 | 2.2.4, 2.2 | 
 |  |  | 
 | 
| | Rule  
                                Disable telnet Service
                                  [ref] |  | Make sure that the activation of the  telnet service on system boot is disabled.
The  telnet socket can be disabled with the following command:
 $ sudo systemctl mask --now telnet.socketWarning: 
                                        If the system relies on xinetdto manage telnet sessions, ensure the telnet service
is disabled by the following line:disable = yes. Note that the xinetd file for
telnet is not created automatically, therefore it might have different names. |  | Rationale: | The telnet protocol uses unencrypted network communication, which means that data from the
login session, including passwords and all other information transmitted during the session,
can be stolen by eavesdroppers on the network. The telnet protocol is also subject to
man-in-the-middle attacks. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_telnet_disabled |  | References: | | cis-csc | 1, 11, 12, 14, 15, 16, 3, 5, 8, 9 |  | cobit5 | APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.06, DSS06.10 |  | cui | 3.1.13, 3.4.7 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, 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 |  | iso27001-2013 | A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.18.1.4, 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.2, A.9.4.3 |  | nist | CM-7(a), CM-7(b), CM-6(a), IA-5(1)(c) |  | nist-csf | PR.AC-1, PR.AC-3, PR.AC-6, PR.AC-7, PR.IP-1, PR.PT-3, PR.PT-4 |  | ism | 1409 | 
 |  |  | 
 | 
| Group  
                Proxy Server
                          Group contains 1 group and 2 rules | 
| [ref]  
                        A proxy server is a very desirable target for a
potential adversary because much (or all) sensitive data for a
given infrastructure may flow through it. Therefore, if one is
required, the system acting as a proxy server should be dedicated
to that purpose alone and be stored in a physically secure
location. The system's default proxy server software is Squid, and
provided in an RPM package of the same name. | 
| Group  
                Disable Squid if Possible
                          Group contains 2 rules | 
| [ref]  
                        If Squid was installed and activated, but the system
does not need to act as a proxy server, then it should be disabled
and removed. | 
| | Rule  
                                Uninstall squid Package
                                  [ref] |  | The  squid package can be removed with the following command:   $ sudo yum erase squid |  | Rationale: | If there is no need to make the proxy server software available,
removing it provides a safeguard against its activation. |  | Severity: | unknown |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_squid_removed |  | References: |  |  |  | 
 | 
| | Rule  
                                Disable Squid
                                  [ref] |  | 
The  squid service can be disabled with the following command:
 $ sudo systemctl mask --now squid.service |  | Rationale: | Running proxy server software provides a network-based avenue
of attack, and should be removed if not needed. |  | Severity: | unknown |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_squid_disabled |  | References: |  |  |  | 
 | 
| Group  
                Network Routing
                          Group contains 1 group and 2 rules | 
| [ref]  
                        A router is a very desirable target for a
potential adversary because they fulfill a variety of 
infrastructure networking roles such as access to network segments,
gateways to other networks, filtering, etc. Therefore, if one is
required, the system acting as a router should be dedicated
to that purpose alone and be stored in a physically secure
location. The system's default routing software is Quagga, and
provided in an RPM package of the same name. | 
| Group  
                Disable Quagga if Possible
                          Group contains 2 rules | 
| [ref]  
                        If Quagga was installed and activated, but the system
does not need to act as a router, then it should be disabled
and removed. | 
| | Rule  
                                Uninstall quagga Package
                                  [ref] |  | The  quagga package can be removed with the following command:   $ sudo yum erase quagga |  | Rationale: | Routing software is typically used on routers to exchange network topology information
with other routers. If routing software is used when not required, system network
information may be unnecessarily transmitted across the network.
If there is no need to make the router software available,
removing it provides a safeguard against its activation.
 |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_package_quagga_removed |  | References: | | cis-csc | 12, 15, 8 |  | cobit5 | APO13.01, DSS05.02 |  | isa-62443-2013 | 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 |  | iso27001-2013 | A.13.1.1, A.13.2.1, A.14.1.3 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.PT-4 |  | os-srg | SRG-OS-000480-GPOS-00227 | 
 |  |  | 
 | 
| | Rule  
                                Disable Quagga Service
                                  [ref] |  | 
The  zebra service can be disabled with the following command:
 $ sudo systemctl mask --now zebra.service |  | Rationale: | Routing protocol daemons are typically used on routers to exchange network
topology information with other routers. If routing daemons are used when not
required, system network information may be unnecessarily transmitted across
the network. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_zebra_disabled |  | References: | | cis-csc | 12, 15, 8 |  | cobit5 | APO13.01, DSS05.02 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2013 | 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 |  | iso27001-2013 | A.13.1.1, A.13.2.1, A.14.1.3 |  | nist | CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.PT-4 |  | os-srg | SRG-OS-000480-GPOS-00227 | 
 |  |  | 
 | 
| Group  
                SSH Server
                          Group contains 1 group and 13 rules | 
| [ref]  
                        The SSH protocol is recommended for remote login and
remote file transfer. SSH provides confidentiality and integrity
for data exchanged between two systems, as well as server
authentication, through the use of public key cryptography. The
implementation included with the system is called OpenSSH, and more
detailed documentation is available from its website,
    https://www.openssh.com .
Its server program is called  sshd and provided by the RPM package
 openssh-server. | 
| Group  
                Configure OpenSSH Server if Necessary
                          Group contains 13 rules | 
| [ref]  
                        If the system needs to act as an SSH server, then
certain changes should be made to the OpenSSH daemon configuration
file  /etc/ssh/sshd_config. The following recommendations can be
applied to this file. See the  sshd_config(5) man page for more
detailed information. | 
| | Rule  
                                Allow Only SSH Protocol 2
                                  [ref] |  | Only SSH protocol version 2 connections should be
permitted. The default setting in
 /etc/ssh/sshd_config is correct, and can be
verified by ensuring that the following
line appears:
 Protocol 2Warning: 
                                        As of  openssh-server version  7.4 and above, the only protocol
supported is version 2, and line  Protocol 2  in
 /etc/ssh/sshd_config is not necessary. |  | Rationale: | SSH protocol version 1 is an insecure implementation of the SSH protocol and
has many well-known vulnerability exploits. Exploits of the SSH daemon could provide
immediate root access to the system. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_allow_only_protocol2 |  | References: | | cis-csc | 1, 12, 15, 16, 5, 8 |  | cjis | 5.5.6 |  | cobit5 | APO13.01, DSS01.04, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10 |  | cui | 3.1.13, 3.5.4 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | SR 1.1, SR 1.10, 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.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 |  | iso27001-2013 | A.11.2.6, A.13.1.1, A.13.2.1, A.14.1.3, A.18.1.4, A.6.2.1, A.6.2.2, 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 |  | nerc-cip | CIP-003-8 R4.2, CIP-007-3 R5.1, CIP-007-3 R7.1 |  | nist | CM-6(a), AC-17(a), AC-17(2), IA-5(1)(c), SC-13, MA-4(6) |  | nist-csf | PR.AC-1, PR.AC-3, PR.AC-6, PR.AC-7, PR.PT-4 |  | os-srg | SRG-OS-000074-GPOS-00042, SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040390 |  | ism | 1483 |  | stigref | SV-221856r987796_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable SSH Access via Empty Passwords
                                  [ref] |  | Disallow SSH login with empty passwords.
The default SSH configuration disables logins with empty passwords. The appropriate
configuration is used if no value is set for  PermitEmptyPasswords.
 
To explicitly disallow SSH login from accounts with empty passwords,
add or correct the following line in
 /etc/ssh/sshd_config:
         PermitEmptyPasswords no 
Any accounts with empty passwords should be disabled immediately, and PAM configuration
should prevent users from being able to assign themselves empty passwords. |  | Rationale: | Configuring this setting for the SSH daemon provides additional assurance
that remote login via SSH will require a password, even in the event of
misconfiguration elsewhere. |  | Severity: | high |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_empty_passwords |  | References: | | cis-csc | 11, 12, 13, 14, 15, 16, 18, 3, 5, 9 |  | cjis | 5.5.6 |  | cobit5 | APO01.06, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.02, DSS06.03, DSS06.06 |  | cui | 3.1.1, 3.1.5 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 5.2, SR 7.6 |  | iso27001-2013 | A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.5.1, A.12.6.2, 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.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5 |  | nist | AC-17(a), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-4, PR.AC-6, PR.DS-5, PR.IP-1, PR.PT-3 |  | ospp | FIA_UAU.1 |  | pcidss | Req-2.2.4 |  | os-srg | SRG-OS-000106-GPOS-00053, SRG-OS-000480-GPOS-00229, SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-010300 |  | ism | 1546 |  | pcidss4 | 2.2.6, 2.2 |  | stigref | SV-221688r958486_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable GSSAPI Authentication
                                  [ref] |  | Unless needed, SSH should not permit extraneous or unnecessary
authentication mechanisms like GSSAPI.
 
The default SSH configuration disallows authentications based on GSSAPI. The appropriate
configuration is used if no value is set for  GSSAPIAuthentication.
 
To explicitly disable GSSAPI authentication, add or correct the following line in
 /etc/ssh/sshd_config:
 GSSAPIAuthentication no |  | Rationale: | GSSAPI authentication is used to provide additional authentication mechanisms to
applications. Allowing GSSAPI authentication through SSH exposes the system's
GSSAPI to remote hosts, increasing the attack surface of the system. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_gssapi_auth |  | References: | | cis-csc | 11, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.1.12 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nist | CM-7(a), CM-7(b), CM-6(a), AC-17(a) |  | nist-csf | PR.IP-1 |  | ospp | FTP_ITC_EXT.1, FCS_SSH_EXT.1.2 |  | os-srg | SRG-OS-000364-GPOS-00151, SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040430 |  | ism | 0418, 1055, 1402 |  | stigref | SV-221860r958796_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable SSH Support for .rhosts Files
                                  [ref] |  | SSH can emulate the behavior of the obsolete rsh
command in allowing users to enable insecure access to their
accounts via  .rhosts files.
 
The default SSH configuration disables support for  .rhosts. The appropriate
configuration is used if no value is set for  IgnoreRhosts.
 
To explicitly disable support for .rhosts files, add or correct the following line in
 /etc/ssh/sshd_config:
 IgnoreRhosts yes |  | Rationale: | SSH trust relationships mean a compromise on one host
can allow an attacker to move trivially to other hosts. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_rhosts |  | References: | | cis-csc | 11, 12, 14, 15, 16, 18, 3, 5, 9 |  | cjis | 5.5.6 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.03, DSS06.06 |  | cui | 3.1.12 |  | isa-62443-2009 | 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.6.1.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5 |  | nist | AC-17(a), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-4, PR.AC-6, PR.IP-1, PR.PT-3 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040350 |  | ism | 1546 |  | pcidss4 | 2.2.6, 2.2 |  | stigref | SV-221852r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable SSH Support for Rhosts RSA Authentication
                                  [ref] |  | SSH can allow authentication through the obsolete rsh
command through the use of the authenticating user's SSH keys. This should be disabled.
 
To ensure this behavior is disabled, add or correct the
following line in  /etc/ssh/sshd_config:
 RhostsRSAAuthentication noWarning: 
                                        As of  openssh-server version  7.4 and above,
the  RhostsRSAAuthentication option has been deprecated, and the line
 RhostsRSAAuthentication no  in  /etc/ssh/sshd_config is not
necessary. |  | Rationale: | Configuring this setting for the SSH daemon provides additional
assurance that remote login via SSH will require a password, even
in the event of misconfiguration elsewhere. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_rhosts_rsa |  | References: | | cis-csc | 11, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.1.12 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nist | AC-17(a), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.IP-1 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040330 |  | stigref | SV-221850r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable SSH Root Login
                                  [ref] |  | The root user should never be allowed to login to a
system directly over a network.
To disable root login via SSH, add or correct the following line in
 /etc/ssh/sshd_config:
 PermitRootLogin no |  | Rationale: | Even though the communications channel may be encrypted, an additional layer of
security is gained by extending the policy of not logging directly on as root.
In addition, logging in with a user-specific account provides individual
accountability of actions performed on the system and also helps to minimize
direct attack attempts on root's password. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_root_login |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 3, 5 |  | cjis | 5.5.6 |  | cobit5 | APO01.06, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.06, DSS06.10 |  | cui | 3.1.1, 3.1.5 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 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.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.2.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3 |  | nist | AC-6(2), AC-17(a), IA-2, IA-2(5), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5, PR.PT-3 |  | ospp | FAU_GEN.1 |  | pcidss | Req-2.2.4 |  | os-srg | SRG-OS-000109-GPOS-00056, SRG-OS-000480-GPOS-00227 |  | app-srg-ctr | SRG-APP-000148-CTR-000335, SRG-APP-000190-CTR-000500 |  | stigid | OL07-00-040370 |  | anssi | R33 |  | ism | 1546 |  | pcidss4 | 2.2.6, 2.2 |  | stigref | SV-221854r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Disable SSH Support for User Known Hosts
                                  [ref] |  | SSH can allow system users to connect to systems if a cache of the remote
systems public keys is available.  This should be disabled.
 
To ensure this behavior is disabled, add or correct the following line in
 /etc/ssh/sshd_config:
 IgnoreUserKnownHosts yes |  | Rationale: | Configuring this setting for the SSH daemon provides additional
assurance that remote login via SSH will require a password, even
in the event of misconfiguration elsewhere. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_disable_user_known_hosts |  | References: | | cis-csc | 11, 3, 9 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.1.12 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nist | AC-17(a), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.IP-1 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040380 |  | ism | 1546 |  | stigref | SV-221855r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Do Not Allow SSH Environment Options
                                  [ref] |  | Ensure that users are not able to override environment variables of the SSH daemon.
 
The default SSH configuration disables environment processing. The appropriate
configuration is used if no value is set for  PermitUserEnvironment.
 
To explicitly disable Environment options, add or correct the following
 /etc/ssh/sshd_config:
 PermitUserEnvironment no |  | Rationale: | SSH environment options potentially allow users to bypass
access restriction in some configurations. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_do_not_permit_user_env |  | References: | | cis-csc | 11, 3, 9 |  | cjis | 5.5.6 |  | cobit5 | BAI10.01, BAI10.02, BAI10.03, BAI10.05 |  | cui | 3.1.12 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.4.3.2, 4.3.4.3.3 |  | isa-62443-2013 | SR 7.6 |  | iso27001-2013 | A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4 |  | nist | AC-17(a), CM-7(a), CM-7(b), CM-6(a) |  | nist-csf | PR.IP-1 |  | pcidss | Req-2.2.4 |  | os-srg | SRG-OS-000480-GPOS-00229 |  | stigid | OL07-00-010460 |  | ism | 1546 |  | pcidss4 | 2.2.6, 2.2 |  | stigref | SV-221696r991591_rule | 
 |  |  | 
 | 
| | Rule  
                                Enable Use of Strict Mode Checking
                                  [ref] |  | SSHs  StrictModes option checks file and ownership permissions in
the user's home directory  .ssh folder before accepting login. If world-
writable permissions are found, logon is rejected.
 
The default SSH configuration has  StrictModes enabled. The appropriate
configuration is used if no value is set for  StrictModes.
 
To explicitly enable  StrictModes in SSH, add or correct the following line in
 /etc/ssh/sshd_config:
 StrictModes yes |  | Rationale: | If other users have access to modify user-specific SSH configuration files, they
may be able to log into the system as another user. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_enable_strictmodes |  | References: | | cis-csc | 12, 13, 14, 15, 16, 18, 3, 5 |  | cobit5 | APO01.06, DSS05.04, DSS05.07, DSS06.02 |  | cui | 3.1.12 |  | hipaa | 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii) |  | isa-62443-2009 | 4.3.3.7.3 |  | isa-62443-2013 | SR 2.1, SR 5.2 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2 |  | nist | AC-6, AC-17(a), CM-6(a) |  | nist-csf | PR.AC-4, PR.DS-5 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040450 |  | ism | 1409 |  | stigref | SV-221862r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Enable SSH Print Last Log
                                  [ref] |  | Ensure that SSH will display the date and time of the last successful account logon.
 
The default SSH configuration enables print of the date and time of the last login.
The appropriate configuration is used if no value is set for  PrintLastLog.
 
To explicitly enable LastLog in SSH, add or correct the following line in
 /etc/ssh/sshd_config:
 PrintLastLog yes |  | Rationale: | Providing users feedback on when account accesses last occurred facilitates user
recognition and reporting of unauthorized account use. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_print_last_log |  | References: | | cis-csc | 1, 12, 15, 16 |  | cobit5 | DSS05.04, DSS05.10, DSS06.10 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9 |  | iso27001-2013 | A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3 |  | nist | AC-9, AC-9(1) |  | nist-csf | PR.AC-7 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | stigid | OL07-00-040360 |  | ism | 0582, 0846 |  | stigref | SV-221853r991589_rule | 
 |  |  | 
 | 
| | Rule  
                                Set LogLevel to INFO
                                  [ref] |  | The INFO parameter specifies that record login and logout activity will be logged.
 
The default SSH configuration sets the log level to INFO. The appropriate
configuration is used if no value is set for  LogLevel.
 
To explicitly specify the log level in SSH, add or correct the following line in
 /etc/ssh/sshd_config:
 LogLevel INFO |  | Rationale: | SSH provides several logging levels with varying amounts of verbosity. DEBUGis specifically
not recommended other than strictly for debugging SSH communications since it provides
so much data that it is difficult to identify important security information.INFOlevel is the
basic level that only records login activity of SSH users. In many situations, such as Incident
Response, it is important to determine when a particular user was active on a system. The
logout record can eliminate those users who disconnected, which helps narrow the field. |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_set_loglevel_info |  | References: |  |  |  | 
 | 
| | Rule  
                                Use Only Strong Ciphers
                                  [ref] |  | Limit the ciphers to strong algorithms.
Counter (CTR) mode is also preferred over cipher-block chaining (CBC) mode.
The following line in  /etc/ssh/sshd_config
demonstrates use of those ciphers:
 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr 
The man page  sshd_config(5) contains a list of supported ciphers. |  | Rationale: | Based on research conducted at various institutions, it was determined that the symmetric
portion of the SSH Transport Protocol (as described in RFC 4253) has security weaknesses
that allowed recovery of up to 32 bits of plaintext from a block of ciphertext that was
encrypted with the Cipher Block Chaining (CBD) method. From that research, new Counter
mode algorithms (as described in RFC4344) were designed that are not vulnerable to these
types of attacks and these algorithms are now recommended for standard use. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_use_strong_ciphers |  |  | 
 | 
| | Rule  
                                Use Only Strong MACs
                                  [ref] |  | Limit the MACs to strong hash algorithms.
The following line in  /etc/ssh/sshd_config demonstrates use
of those MACs:
 MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160
         |  | Rationale: | MD5 and 96-bit MAC algorithms are considered weak and have been shown to increase
exploitability in SSH downgrade attacks. Weak algorithms continue to have a great deal of
attention as a weak spot that can be exploited with expanded computing power. An
attacker that breaks the algorithm could take advantage of a MiTM position to decrypt the
SSH tunnel and capture credentials and information |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_sshd_use_strong_macs |  | References: |  |  |  | 
 | 
| Group  
                System Accounting with auditd
                          Group contains 7 groups and 28 rules | 
| [ref]  
                        The audit service provides substantial capabilities
for recording system activities. By default, the service audits about
SELinux AVC denials and certain types of security-relevant events
such as system logins, account modifications, and authentication
events performed by programs such as sudo.
Under its default configuration,  auditd has modest disk space
requirements, and should not noticeably impact system performance.
      
NOTE: The Linux Audit daemon  auditd can be configured to use
the  augenrules program to read audit rules files ( *.rules)
located in  /etc/audit/rules.d location and compile them to create
the resulting form of the  /etc/audit/audit.rules configuration file
during the daemon startup (default configuration). Alternatively, the  auditd
daemon can use the  auditctl utility to read audit rules from the
 /etc/audit/audit.rules configuration file during daemon startup,
and load them into the kernel. The expected behavior is configured via the
appropriate  ExecStartPost directive setting in the
 /usr/lib/systemd/system/auditd.service configuration file.
To instruct the  auditd daemon to use the  augenrules program
to read audit rules (default configuration), use the following setting:
      ExecStartPost=-/sbin/augenrules --load 
in the  /usr/lib/systemd/system/auditd.service configuration file.
In order to instruct the  auditd daemon to use the  auditctl
utility to read audit rules, use the following setting:
      ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules 
in the  /usr/lib/systemd/system/auditd.service configuration file.
Refer to  [Service] section of the  /usr/lib/systemd/system/auditd.service
configuration file for further details.
      
Government networks often have substantial auditing
requirements and  auditd can be configured to meet these
requirements.
Examining some example audit records demonstrates how the Linux audit system
satisfies common requirements.
The following example from Red Hat Enterprise Linux 7 Documentation available at
 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html-single/selinux_users_and_administrators_guide/index#sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages
shows the substantial amount of information captured in a
two typical "raw" audit messages, followed by a breakdown of the most important
fields. In this example the message is SELinux-related and reports an AVC
denial (and the associated system call) that occurred when the Apache HTTP
Server attempted to access the  /var/www/html/file1 file (labeled with
the  samba_share_t type):
 type=AVC msg=audit(1226874073.147:96): avc:  denied  { getattr } for pid=2465 comm="httpd"
path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file
type=SYSCALL msg=audit(1226874073.147:96): arch=40000003 syscall=196 success=no exit=-13
a0=b98df198 a1=bfec85dc a2=54dff4 a3=2008171 items=0 ppid=2463 pid=2465 auid=502 uid=48
gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=6 comm="httpd"
exe="/usr/sbin/httpd" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
msg=audit(1226874073.147:96)The number in parentheses is the unformatted time stamp (Epoch time)
for the event, which can be converted to standard time by using the
datecommand.
{ getattr }The item in braces indicates the permission that was denied. getattrindicates the source process was trying to read the target file's status information.
This occurs before reading files. This action is denied due to the file being
accessed having the wrong label. Commonly seen permissions includegetattr,read, andwrite.
comm="httpd"The executable that launched the process. The full path of the executable is
found in the exe=section of the system call (SYSCALL) message,
which in this case, isexe="/usr/sbin/httpd".
path="/var/www/html/file1"The path to the object (target) the process attempted to access.
scontext="unconfined_u:system_r:httpd_t:s0"The SELinux context of the process that attempted the denied action. In
this case, it is the SELinux context of the Apache HTTP Server, which is running
in the httpd_tdomain.
tcontext="unconfined_u:object_r:samba_share_t:s0"The SELinux context of the object (target) the process attempted to access.
In this case, it is the SELinux context of file1. Note: thesamba_share_ttype is not accessible to processes running in thehttpd_tdomain.
 From the system call (SYSCALL) message, two items are of interest:success=no: indicates whether the denial (AVC) was enforced or not.success=noindicates the system call was not successful (SELinux denied
access).success=yesindicates the system call was successful - this can
be seen for permissive domains or unconfined domains, such asinitrc_tandkernel_t.exe="/usr/sbin/httpd": the full path to the executable that launched
the process, which in this case, isexe="/usr/sbin/httpd".
 | 
| Group  
                Configure auditd Rules for Comprehensive Auditing
                          Group contains 5 groups and 21 rules | 
| [ref]  
                        The  auditd program can perform comprehensive
monitoring of system activity. This section describes recommended
configuration settings for comprehensive auditing, but a full
description of the auditing system's capabilities is beyond the
scope of this guide. The mailing list linux-audit@redhat.com  exists
to facilitate community discussion of the auditing system.
       
The audit subsystem supports extensive collection of events, including:
       Tracing of arbitrary system calls (identified by name or number)
on entry or exit.Filtering by PID, UID, call success, system call argument (with
some limitations), etc.Monitoring of specific files for modifications to the file's
contents or metadata.
 
Auditing rules at startup are controlled by the file  /etc/audit/audit.rules.
Add rules to it to meet the auditing requirements for your organization.
Each line in  /etc/audit/audit.rules represents a series of arguments
that can be passed to  auditctl and can be individually tested
during runtime. See documentation in  /usr/share/doc/audit-VERSION
       and
in the related man pages for more details.
       
If copying any example audit rulesets from  /usr/share/doc/audit-VERSION,
be sure to comment out the
lines containing  arch= which are not appropriate for your system's
architecture. Then review and understand the following rules,
ensuring rules are activated as needed for the appropriate
architecture.
       
After reviewing all the rules, reading the following sections, and
editing as needed, the new rules can be activated as follows:
 $ sudo service auditd restart | 
| Group  
                Record Events that Modify the System's Discretionary Access Controls
                          Group contains 2 rules | 
| [ref]  
                        At a minimum, the audit system should collect file permission
changes for all users and root. Note that the "-F arch=b32" lines should be
present even on a 64 bit system. These commands identify system calls for
auditing. Even if the system is 64 bit it can still execute 32 bit system
calls. Additionally, these rules can be configured in a number of ways while
still achieving the desired effect. An example of this is that the "-S" calls
could be split up and placed on separate lines, however, this is less efficient.
Add the following to  /etc/audit/audit.rules:
 -a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    -a always,exit -F arch=b32 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    -a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod
If your system is 64 bit then these lines should be duplicated and the
arch=b32 replaced with arch=b64 as follows:
 -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
    -a always,exit -F arch=b64 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=unset -F key=perm_mod
    -a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod | 
| | Rule  
                                Record Events that Modify the System's Discretionary Access Controls - chmod
                                  [ref] |  | 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_modWarning: 
                                        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. |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chmod |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.5.5 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000064-GPOS-00033, SRG-OS-000466-GPOS-00210, SRG-OS-000458-GPOS-00203 |  | app-srg-ctr | SRG-APP-000091-CTR-000160, SRG-APP-000492-CTR-001220, SRG-APP-000493-CTR-001225, SRG-APP-000494-CTR-001230, SRG-APP-000500-CTR-001260, SRG-APP-000507-CTR-001295, SRG-APP-000495-CTR-001235, SRG-APP-000499-CTR-001255 |  | stigid | OL07-00-030410 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.3.4, 10.3 |  | stigref | SV-221782r991570_rule | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek && { ! ( ( grep -sqE "^.*\.aarch64$" /proc/sys/kernel/osrelease || grep -sqE "^aarch64$" /proc/sys/kernel/arch; ) ); }; 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
	ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
	OTHER_FILTERS=""
	AUID_FILTERS="-F auid>=1000 -F auid!=unset"
	SYSCALL="chmod"
	KEY="perm_mod"
	SYSCALL_GROUPING="chmod fchmod fchmodat"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# 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
default_file="/etc/audit/rules.d/$KEY.rules"
# As other_filters may include paths, lets use a different delimiter for it
# The "F" script expression tells sed to print the filenames where the expressions matched
readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
# 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 0600 "$file_to_inspect"
    fi
fi
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
default_file="/etc/audit/audit.rules"
files_to_inspect+=('/etc/audit/audit.rules' )
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | true | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030410
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chmod
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Set architecture for audit chmod tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030410
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chmod
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for chmod for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chmod
      syscall_grouping:
      - chmod
      - fchmod
      - fchmodat
  - name: Check existence of chmod in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chmod
      syscall_grouping:
      - chmod
      - fchmod
      - fchmodat
  - name: Check existence of chmod in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030410
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chmod
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for chmod for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chmod
      syscall_grouping:
      - chmod
      - fchmod
      - fchmodat
  - name: Check existence of chmod in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chmod
      syscall_grouping:
      - chmod
      - fchmod
      - fchmodat
  - name: Check existence of chmod in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030410
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chmod
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
 | 
 | 
| | Rule  
                                Record Events that Modify the System's Discretionary Access Controls - chown
                                  [ref] |  | 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_modWarning: 
                                        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. |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_dac_modification_chown |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.5.5 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000064-GPOS-00033, SRG-OS-000466-GPOS-00210, SRG-OS-000458-GPOS-00203, SRG-OS-000474-GPOS-00219 |  | app-srg-ctr | SRG-APP-000091-CTR-000160, SRG-APP-000492-CTR-001220, SRG-APP-000493-CTR-001225, SRG-APP-000494-CTR-001230, SRG-APP-000500-CTR-001260, SRG-APP-000507-CTR-001295, SRG-APP-000495-CTR-001235, SRG-APP-000499-CTR-001255 |  | stigid | OL07-00-030370 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.3.4, 10.3 |  | stigref | SV-221778r958446_rule | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek && { ! ( ( grep -sqE "^.*\.aarch64$" /proc/sys/kernel/osrelease || grep -sqE "^aarch64$" /proc/sys/kernel/arch; ) ); }; 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
	ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
	OTHER_FILTERS=""
	AUID_FILTERS="-F auid>=1000 -F auid!=unset"
	SYSCALL="chown"
	KEY="perm_mod"
	SYSCALL_GROUPING="chown fchown fchownat lchown"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# 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
default_file="/etc/audit/rules.d/$KEY.rules"
# As other_filters may include paths, lets use a different delimiter for it
# The "F" script expression tells sed to print the filenames where the expressions matched
readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
# 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 0600 "$file_to_inspect"
    fi
fi
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
default_file="/etc/audit/audit.rules"
files_to_inspect+=('/etc/audit/audit.rules' )
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | true | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030370
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chown
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Set architecture for audit chown tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030370
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chown
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for chown for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chown
      syscall_grouping:
      - chown
      - fchown
      - fchownat
      - lchown
  - name: Check existence of chown in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chown
      syscall_grouping:
      - chown
      - fchown
      - fchownat
      - lchown
  - name: Check existence of chown in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030370
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chown
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for chown for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chown
      syscall_grouping:
      - chown
      - fchown
      - fchownat
      - lchown
  - name: Check existence of chown in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - chown
      syscall_grouping:
      - chown
      - fchown
      - fchownat
      - lchown
  - name: Check existence of chown in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=perm_mod
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - not ( ansible_architecture == "aarch64" )
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - DISA-STIG-OL07-00-030370
  - NIST-800-171-3.1.7
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_dac_modification_chown
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
 | 
 | 
| Group  
                Record Execution Attempts to Run SELinux Privileged Commands
                          Group contains 6 rules | 
| [ref]  
                        At a minimum, the audit system should collect the execution of
SELinux privileged commands for all users and root. | 
| | Rule  
                                Record Any Attempts to Run chcon
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_chcon |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, BAI03.05, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.PT-1 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000468-GPOS-00212, SRG-OS-000471-GPOS-00215, SRG-OS-000463-GPOS-00207, SRG-OS-000465-GPOS-00209 |  | app-srg-ctr | SRG-APP-000495-CTR-001235, SRG-APP-000496-CTR-001240, SRG-APP-000497-CTR-001245, SRG-APP-000498-CTR-001250, SRG-APP-000501-CTR-001265, SRG-APP-000502-CTR-001270 |  | stigid | OL07-00-030580 |  | ism | 0582 |  | stigref | SV-221799r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Any Attempts to Run restorecon
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/sbin/restorecon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/sbin/restorecon -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_restorecon |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, BAI03.05, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.PT-1 |  | os-srg | SRG-OS-000392-GPOS-00172, SRG-OS-000463-GPOS-00207, SRG-OS-000465-GPOS-00209 |  | ism | 0582 | 
 |  |  | 
 | 
| | Rule  
                                Record Any Attempts to Run semanage
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_semanage |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, BAI03.05, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2 |  | nerc-cip | CIP-004-6 R2.2.2, CIP-004-6 R2.2.3, CIP-007-3 R.1.3, CIP-007-3 R5, CIP-007-3 R5.1.1, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3 |  | nist | AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.PT-1 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000463-GPOS-00207, SRG-OS-000465-GPOS-00209 |  | app-srg-ctr | SRG-APP-000495-CTR-001235, SRG-APP-000496-CTR-001240, SRG-APP-000497-CTR-001245, SRG-APP-000498-CTR-001250 |  | stigid | OL07-00-030560 |  | ism | 0582 |  | stigref | SV-221797r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Any Attempts to Run setfiles
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_setfiles |  | References: | | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000463-GPOS-00207, SRG-OS-000465-GPOS-00209 |  | app-srg-ctr | SRG-APP-000495-CTR-001235, SRG-APP-000496-CTR-001240, SRG-APP-000497-CTR-001245, SRG-APP-000498-CTR-001250 |  | stigid | OL07-00-030590 |  | ism | 0582 |  | stigref | SV-221800r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Any Attempts to Run setsebool
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_setsebool |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, BAI03.05, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.PT-1 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000463-GPOS-00207, SRG-OS-000465-GPOS-00209 |  | app-srg-ctr | SRG-APP-000495-CTR-001235, SRG-APP-000496-CTR-001240, SRG-APP-000497-CTR-001245, SRG-APP-000498-CTR-001250 |  | stigid | OL07-00-030570 |  | ism | 0582 |  | stigref | SV-221798r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Any Attempts to Run seunshare
                                  [ref] |  | 
At a minimum, the audit system should collect the execution of privileged
commands 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
a line of the following form to a file with suffix  .rules
in the directory  /etc/audit/rules.d:
 -a always,exit -F path=/usr/sbin/seunshare -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged 
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:
 -a always,exit -F path=/usr/sbin/seunshare -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged |  | 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 threats.
 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.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_execution_seunshare |  | References: | | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | ism | 0582 | 
 |  |  | 
 | 
| Group  
                Record Information on Kernel Modules Loading and Unloading
                          Group contains  1 rule | 
| [ref]  
                        To capture kernel module loading and unloading events, use following lines, 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,delete_module -F key=modules
 
Place to add the lines depends on a way  auditd daemon is configured. If it is configured
to use the  augenrules program (the default), add the lines 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 lines to file  /etc/audit/audit.rules. | 
| | Rule  
                                Ensure auditd Collects Information on Kernel Module Loading and Unloading
                                  [ref] |  | To capture kernel module loading and unloading events, use following lines, 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,finit_module,delete_module -F auid>=1000 -F auid!=unset -F key=modules
 
The place to add the lines depends on a way  auditd daemon is configured. If it is configured
to use the  augenrules program (the default), add the lines 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 lines to file  /etc/audit/audit.rules. |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.7 |  | ism | 0582 | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek; 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
        ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
        OTHER_FILTERS=""
        
        AUID_FILTERS="-F auid>=1000 -F auid!=unset"
        
        SYSCALL="init_module finit_module delete_module"
        KEY="modules"
        SYSCALL_GROUPING="init_module finit_module delete_module"
        # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
        unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# 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
default_file="/etc/audit/rules.d/$KEY.rules"
# As other_filters may include paths, lets use a different delimiter for it
# The "F" script expression tells sed to print the filenames where the expressions matched
readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
# 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 0600 "$file_to_inspect"
    fi
fi
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
        unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
default_file="/etc/audit/audit.rules"
files_to_inspect+=('/etc/audit/audit.rules' )
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | true | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.2.7
  - audit_rules_kernel_module_loading
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Set architecture for audit tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.2.7
  - audit_rules_kernel_module_loading
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for kernel module loading for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - init_module
      - delete_module
      - finit_module
      syscall_grouping:
      - init_module
      - delete_module
      - finit_module
  - name: Check existence of init_module, delete_module, finit_module in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=modules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - init_module
      - delete_module
      - finit_module
      syscall_grouping:
      - init_module
      - delete_module
      - finit_module
  - name: Check existence of init_module, delete_module, finit_module in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=modules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.2.7
  - audit_rules_kernel_module_loading
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
- name: Perform remediation of Audit rules for kernel module loading for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - init_module
      - delete_module
      - finit_module
      syscall_grouping:
      - init_module
      - delete_module
      - finit_module
  - name: Check existence of init_module, delete_module, finit_module in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
        |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=modules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - init_module
      - delete_module
      - finit_module
      syscall_grouping:
      - init_module
      - delete_module
      - finit_module
  - name: Check existence of init_module, delete_module, finit_module in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k |-F
        key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
        -F auid!=unset -F key=modules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.2.7
  - audit_rules_kernel_module_loading
  - low_complexity
  - low_disruption
  - medium_severity
  - reboot_required
  - restrict_strategy
 | 
 | 
| Group  
                Record Attempts to Alter Logon and Logout Events
                          Group contains 4 rules | 
| [ref]  
                        The audit system already collects login 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 logon events:
 -w /var/log/tallylog -p wa -k logins
-w /var/log/faillock -p wa -k logins
-w /var/log/lastlog -p wa -k logins 
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 unattempted manual
edits of files involved in storing logon events:
 -w /var/log/tallylog -p wa -k logins
-w /var/log/faillock -p wa -k logins
-w /var/log/lastlog -p wa -k logins | 
| | Rule  
                                Record Attempts to Alter Logon and Logout Events
                                  [ref] |  | The audit system already collects login 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 logon events:
 -w /var/log/tallylog -p wa -k logins
-w /var/log/faillock -p wa -k logins
-w /var/log/lastlog -p wa -k logins 
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 unattempted manual
edits of files involved in storing logon events:
 -w /var/log/tallylog -p wa -k logins
-w /var/log/faillock -p wa -k logins
-w /var/log/lastlog -p wa -k loginsWarning: 
                                        This rule checks for multiple syscalls related to login events;
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_login_events_tallylogaudit_rules_login_events_faillockaudit_rules_login_events_lastlog
 |  | Rationale: | Manual editing of these files may indicate nefarious activity, such
as an attacker attempting to remove evidence of an intrusion. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_login_events |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.3 | 
 |  |  | 
 | 
| | Rule  
                                Record Attempts to Alter Logon and Logout Events - faillock
                                  [ref] |  | The audit system already collects login 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:
 -w /var/log/faillock -p wa -k logins 
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:
 -w /var/log/faillock -p wa -k logins |  | Rationale: | Manual editing of these files may indicate nefarious activity, such
as an attacker attempting to remove evidence of an intrusion. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_login_events_faillock |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.3 |  | os-srg | SRG-OS-000392-GPOS-00172, SRG-OS-000470-GPOS-00214, SRG-OS-000473-GPOS-00218 |  | app-srg-ctr | SRG-APP-000503-CTR-001275, SRG-APP-000506-CTR-001290 |  | stigid | OL07-00-030610 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.2.1.3, 10.2.1, 10.2 |  | stigref | SV-221801r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Attempts to Alter Logon and Logout Events - lastlog
                                  [ref] |  | The audit system already collects login 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:
 -w /var/log/lastlog -p wa -k logins 
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:
 -w /var/log/lastlog -p wa -k logins |  | Rationale: | Manual editing of these files may indicate nefarious activity, such
as an attacker attempting to remove evidence of an intrusion. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_login_events_lastlog |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.3 |  | os-srg | SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000473-GPOS-00218, SRG-OS-000470-GPOS-00214 |  | app-srg-ctr | SRG-APP-000495-CTR-001235, SRG-APP-000503-CTR-001275, SRG-APP-000506-CTR-001290 |  | stigid | OL07-00-030620 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.2.1.3, 10.2.1, 10.2 |  | stigref | SV-221802r958846_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Attempts to Alter Logon and Logout Events - tallylog
                                  [ref] |  | The audit system already collects login 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:
 -w /var/log/tallylog -p wa -k logins 
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:
 -w /var/log/tallylog -p wa -k logins |  | Rationale: | Manual editing of these files may indicate nefarious activity, such
as an attacker attempting to remove evidence of an intrusion. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_login_events_tallylog |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.3 |  | os-srg | SRG-OS-000392-GPOS-00172, SRG-OS-000470-GPOS-00214, SRG-OS-000473-GPOS-00218 |  | app-srg-ctr | SRG-APP-000503-CTR-001275 |  | ism | 0582 |  | pcidss4 | 10.2.1.3, 10.2.1, 10.2 | 
 |  |  | 
 | 
| Group  
                Records Events that Modify Date and Time Information
                          Group contains 5 rules | 
| [ref]  
                        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. All changes to the system
time should be audited. | 
| | Rule  
                                Record attempts to alter time through adjtimex
                                  [ref] |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_time_adjtimex |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.4.2.b |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.6.3, 10.6 | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek; then
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")
for ARCH in "${RULE_ARCHS[@]}"
do
    # Create expected audit group and audit rule form for particular system call & architecture
    if [ ${ARCH} = "b32" ]
    then
        ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
        # 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
        SYSCALL="adjtimex settimeofday stime"
        SYSCALL_GROUPING="adjtimex settimeofday stime"
    elif [ ${ARCH} = "b64" ]
    then
        ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
        # 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
        SYSCALL="adjtimex settimeofday"
        SYSCALL_GROUPING="adjtimex settimeofday"
    fi
    OTHER_FILTERS=""
    AUID_FILTERS=""
    KEY="audit_time_rules"
    # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
    unset syscall_a
    unset syscall_grouping
    unset syscall_string
    unset syscall
    unset file_to_edit
    unset rule_to_edit
    unset rule_syscalls_to_edit
    unset other_string
    unset auid_string
    unset full_rule
    # Load macro arguments into arrays
    read -a syscall_a <<< $SYSCALL
    read -a syscall_grouping <<< $SYSCALL_GROUPING
    # 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  |
    # -----------------------------------------------------------------------------------------
    #
    files_to_inspect=()
    # 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
    default_file="/etc/audit/rules.d/$KEY.rules"
    # As other_filters may include paths, lets use a different delimiter for it
    # The "F" script expression tells sed to print the filenames where the expressions matched
    readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
    # 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 0600 "$file_to_inspect"
        fi
    fi
    # After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
    skip=1
    for audit_file in "${files_to_inspect[@]}"
    do
        # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
        # i.e, collect rules that match:
        # * the action, list and arch, (2-nd argument)
        # * the other filters, (3-rd argument)
        # * the auid filters, (4-rd argument)
        readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
        candidate_rules=()
        # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
        for s_rule in "${similar_rules[@]}"
        do
            # Strip all the options and fields we know of,
            # than check if there was any field left over
            extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
            grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
        done
        if [[ ${#syscall_a[@]} -ge 1 ]]
        then
            # Check if the syscall we want is present in any of the similar existing rules
            for rule in "${candidate_rules[@]}"
            do
                rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
                all_syscalls_found=0
                for syscall in "${syscall_a[@]}"
                do
                    grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                       # A syscall was not found in the candidate rule
                       all_syscalls_found=1
                       }
                done
                if [[ $all_syscalls_found -eq 0 ]]
                then
                    # We found a rule with all the syscall(s) we want; skip rest of macro
                    skip=0
                    break
                fi
                # Check if this rule can be grouped with our target syscall and keep track of it
                for syscall_g in "${syscall_grouping[@]}"
                do
                    if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                    then
                        file_to_edit=${audit_file}
                        rule_to_edit=${rule}
                        rule_syscalls_to_edit=${rule_syscalls}
                    fi
                done
            done
        else
            # If there is any candidate rule, it is compliant; skip rest of macro
            if [ "${#candidate_rules[@]}" -gt 0 ]
            then
                skip=0
            fi
        fi
        if [ "$skip" -eq 0 ]; then
            break
        fi
    done
    if [ "$skip" -ne 0 ]; then
        # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
        # At this point we know if we need to either append the $full_rule or group
        # the syscall together with an exsiting rule
        # Append the full_rule if it cannot be grouped to any other rule
        if [ -z ${rule_to_edit+x} ]
        then
            # Build full_rule while avoid adding double spaces when other_filters is empty
            if [ "${#syscall_a[@]}" -gt 0 ]
            then
                syscall_string=""
                for syscall in "${syscall_a[@]}"
                do
                    syscall_string+=" -S $syscall"
                done
            fi
            other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
            auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
            full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
            echo "$full_rule" >> "$default_file"
            chmod 0600 ${default_file}
        else
            # Check if the syscalls are declared as a comma separated list or
            # as multiple -S parameters
            if grep -q -- "," <<< "${rule_syscalls_to_edit}"
            then
                delimiter=","
            else
                delimiter=" -S "
            fi
            new_grouped_syscalls="${rule_syscalls_to_edit}"
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
                   # A syscall was not found in the candidate rule
                   new_grouped_syscalls+="${delimiter}${syscall}"
                   }
            done
            # Group the syscall in the rule
            sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
        fi
    fi
    unset syscall_a
    unset syscall_grouping
    unset syscall_string
    unset syscall
    unset file_to_edit
    unset rule_to_edit
    unset rule_syscalls_to_edit
    unset other_string
    unset auid_string
    unset full_rule
    # Load macro arguments into arrays
    read -a syscall_a <<< $SYSCALL
    read -a syscall_grouping <<< $SYSCALL_GROUPING
    # 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  |
    # -----------------------------------------------------------------------------------------
    #
    files_to_inspect=()
    # If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
    # file to the list of files to be inspected
    default_file="/etc/audit/audit.rules"
    files_to_inspect+=('/etc/audit/audit.rules' )
    # After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
    skip=1
    for audit_file in "${files_to_inspect[@]}"
    do
        # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
        # i.e, collect rules that match:
        # * the action, list and arch, (2-nd argument)
        # * the other filters, (3-rd argument)
        # * the auid filters, (4-rd argument)
        readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
        candidate_rules=()
        # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
        for s_rule in "${similar_rules[@]}"
        do
            # Strip all the options and fields we know of,
            # than check if there was any field left over
            extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
            grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
        done
        if [[ ${#syscall_a[@]} -ge 1 ]]
        then
            # Check if the syscall we want is present in any of the similar existing rules
            for rule in "${candidate_rules[@]}"
            do
                rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
                all_syscalls_found=0
                for syscall in "${syscall_a[@]}"
                do
                    grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                       # A syscall was not found in the candidate rule
                       all_syscalls_found=1
                       }
                done
                if [[ $all_syscalls_found -eq 0 ]]
                then
                    # We found a rule with all the syscall(s) we want; skip rest of macro
                    skip=0
                    break
                fi
                # Check if this rule can be grouped with our target syscall and keep track of it
                for syscall_g in "${syscall_grouping[@]}"
                do
                    if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                    then
                        file_to_edit=${audit_file}
                        rule_to_edit=${rule}
                        rule_syscalls_to_edit=${rule_syscalls}
                    fi
                done
            done
        else
            # If there is any candidate rule, it is compliant; skip rest of macro
            if [ "${#candidate_rules[@]}" -gt 0 ]
            then
                skip=0
            fi
        fi
        if [ "$skip" -eq 0 ]; then
            break
        fi
    done
    if [ "$skip" -ne 0 ]; then
        # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
        # At this point we know if we need to either append the $full_rule or group
        # the syscall together with an exsiting rule
        # Append the full_rule if it cannot be grouped to any other rule
        if [ -z ${rule_to_edit+x} ]
        then
            # Build full_rule while avoid adding double spaces when other_filters is empty
            if [ "${#syscall_a[@]}" -gt 0 ]
            then
                syscall_string=""
                for syscall in "${syscall_a[@]}"
                do
                    syscall_string+=" -S $syscall"
                done
            fi
            other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
            auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
            full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
            echo "$full_rule" >> "$default_file"
            chmod 0600 ${default_file}
        else
            # Check if the syscalls are declared as a comma separated list or
            # as multiple -S parameters
            if grep -q -- "," <<< "${rule_syscalls_to_edit}"
            then
                delimiter=","
            else
                delimiter=" -S "
            fi
            new_grouped_syscalls="${rule_syscalls_to_edit}"
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
                   # A syscall was not found in the candidate rule
                   new_grouped_syscalls+="${delimiter}${syscall}"
                   }
            done
            # Group the syscall in the rule
            sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
        fi
    fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | false | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_adjtimex
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Set architecture for audit tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_adjtimex
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for adjtimex for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - adjtimex
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of adjtimex in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_time_rules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - adjtimex
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of adjtimex in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_adjtimex
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for adjtimex for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - adjtimex
      syscall_grouping:
      - adjtimex
      - settimeofday
  - name: Check existence of adjtimex in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_time_rules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - adjtimex
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of adjtimex in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_adjtimex
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
 | 
 | 
| | Rule  
                                Record Attempts to Alter Time Through clock_settime
                                  [ref] |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_time_clock_settime |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.4.2.b |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.6.3, 10.6 | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek; 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
	ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
	OTHER_FILTERS="-F a0=0x0"
	AUID_FILTERS=""
	SYSCALL="clock_settime"
	KEY="time-change"
	SYSCALL_GROUPING=""
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# 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
default_file="/etc/audit/rules.d/$KEY.rules"
# As other_filters may include paths, lets use a different delimiter for it
# The "F" script expression tells sed to print the filenames where the expressions matched
readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
# 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 0600 "$file_to_inspect"
    fi
fi
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
default_file="/etc/audit/audit.rules"
files_to_inspect+=('/etc/audit/audit.rules' )
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | false | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_clock_settime
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Set architecture for audit tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_clock_settime
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for clock_settime for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - clock_settime
      syscall_grouping: []
  - name: Check existence of clock_settime in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F a0=0x0 (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/time-change.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/time-change.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F a0=0x0 (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F a0=0x0 -F
        key=time-change
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - clock_settime
      syscall_grouping: []
  - name: Check existence of clock_settime in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F a0=0x0 (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F a0=0x0 (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F a0=0x0 -F
        key=time-change
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_clock_settime
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for clock_settime for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - clock_settime
      syscall_grouping: []
  - name: Check existence of clock_settime in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F a0=0x0 (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/time-change.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/time-change.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( -F a0=0x0 (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F a0=0x0 -F
        key=time-change
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - clock_settime
      syscall_grouping: []
  - name: Check existence of clock_settime in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* -F a0=0x0 (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( -F a0=0x0 (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F a0=0x0 -F
        key=time-change
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_clock_settime
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
 | 
 | 
| | Rule  
                                Record attempts to alter time through settimeofday
                                  [ref] |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_time_settimeofday |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.4.2.b |  | ism | 0582 |  | pcidss4 | 10.6.3, 10.6 | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek; then
# Retrieve hardware architecture of the underlying system
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")
for ARCH in "${RULE_ARCHS[@]}"
do
    # Create expected audit group and audit rule form for particular system call & architecture
    if [ ${ARCH} = "b32" ]
    then
        ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
        # 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
        SYSCALL="adjtimex settimeofday stime"
        SYSCALL_GROUPING="adjtimex settimeofday stime"
    elif [ ${ARCH} = "b64" ]
    then
        ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
        # 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
        SYSCALL="adjtimex settimeofday"
        SYSCALL_GROUPING="adjtimex settimeofday"
    fi
    OTHER_FILTERS=""
    AUID_FILTERS=""
    KEY="audit_time_rules"
    # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
    unset syscall_a
    unset syscall_grouping
    unset syscall_string
    unset syscall
    unset file_to_edit
    unset rule_to_edit
    unset rule_syscalls_to_edit
    unset other_string
    unset auid_string
    unset full_rule
    # Load macro arguments into arrays
    read -a syscall_a <<< $SYSCALL
    read -a syscall_grouping <<< $SYSCALL_GROUPING
    # 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  |
    # -----------------------------------------------------------------------------------------
    #
    files_to_inspect=()
    # 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
    default_file="/etc/audit/rules.d/$KEY.rules"
    # As other_filters may include paths, lets use a different delimiter for it
    # The "F" script expression tells sed to print the filenames where the expressions matched
    readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
    # 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 0600 "$file_to_inspect"
        fi
    fi
    # After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
    skip=1
    for audit_file in "${files_to_inspect[@]}"
    do
        # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
        # i.e, collect rules that match:
        # * the action, list and arch, (2-nd argument)
        # * the other filters, (3-rd argument)
        # * the auid filters, (4-rd argument)
        readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
        candidate_rules=()
        # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
        for s_rule in "${similar_rules[@]}"
        do
            # Strip all the options and fields we know of,
            # than check if there was any field left over
            extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
            grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
        done
        if [[ ${#syscall_a[@]} -ge 1 ]]
        then
            # Check if the syscall we want is present in any of the similar existing rules
            for rule in "${candidate_rules[@]}"
            do
                rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
                all_syscalls_found=0
                for syscall in "${syscall_a[@]}"
                do
                    grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                       # A syscall was not found in the candidate rule
                       all_syscalls_found=1
                       }
                done
                if [[ $all_syscalls_found -eq 0 ]]
                then
                    # We found a rule with all the syscall(s) we want; skip rest of macro
                    skip=0
                    break
                fi
                # Check if this rule can be grouped with our target syscall and keep track of it
                for syscall_g in "${syscall_grouping[@]}"
                do
                    if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                    then
                        file_to_edit=${audit_file}
                        rule_to_edit=${rule}
                        rule_syscalls_to_edit=${rule_syscalls}
                    fi
                done
            done
        else
            # If there is any candidate rule, it is compliant; skip rest of macro
            if [ "${#candidate_rules[@]}" -gt 0 ]
            then
                skip=0
            fi
        fi
        if [ "$skip" -eq 0 ]; then
            break
        fi
    done
    if [ "$skip" -ne 0 ]; then
        # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
        # At this point we know if we need to either append the $full_rule or group
        # the syscall together with an exsiting rule
        # Append the full_rule if it cannot be grouped to any other rule
        if [ -z ${rule_to_edit+x} ]
        then
            # Build full_rule while avoid adding double spaces when other_filters is empty
            if [ "${#syscall_a[@]}" -gt 0 ]
            then
                syscall_string=""
                for syscall in "${syscall_a[@]}"
                do
                    syscall_string+=" -S $syscall"
                done
            fi
            other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
            auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
            full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
            echo "$full_rule" >> "$default_file"
            chmod 0600 ${default_file}
        else
            # Check if the syscalls are declared as a comma separated list or
            # as multiple -S parameters
            if grep -q -- "," <<< "${rule_syscalls_to_edit}"
            then
                delimiter=","
            else
                delimiter=" -S "
            fi
            new_grouped_syscalls="${rule_syscalls_to_edit}"
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
                   # A syscall was not found in the candidate rule
                   new_grouped_syscalls+="${delimiter}${syscall}"
                   }
            done
            # Group the syscall in the rule
            sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
        fi
    fi
    unset syscall_a
    unset syscall_grouping
    unset syscall_string
    unset syscall
    unset file_to_edit
    unset rule_to_edit
    unset rule_syscalls_to_edit
    unset other_string
    unset auid_string
    unset full_rule
    # Load macro arguments into arrays
    read -a syscall_a <<< $SYSCALL
    read -a syscall_grouping <<< $SYSCALL_GROUPING
    # 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  |
    # -----------------------------------------------------------------------------------------
    #
    files_to_inspect=()
    # If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
    # file to the list of files to be inspected
    default_file="/etc/audit/audit.rules"
    files_to_inspect+=('/etc/audit/audit.rules' )
    # After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
    skip=1
    for audit_file in "${files_to_inspect[@]}"
    do
        # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
        # i.e, collect rules that match:
        # * the action, list and arch, (2-nd argument)
        # * the other filters, (3-rd argument)
        # * the auid filters, (4-rd argument)
        readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
        candidate_rules=()
        # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
        for s_rule in "${similar_rules[@]}"
        do
            # Strip all the options and fields we know of,
            # than check if there was any field left over
            extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
            grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
        done
        if [[ ${#syscall_a[@]} -ge 1 ]]
        then
            # Check if the syscall we want is present in any of the similar existing rules
            for rule in "${candidate_rules[@]}"
            do
                rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
                all_syscalls_found=0
                for syscall in "${syscall_a[@]}"
                do
                    grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                       # A syscall was not found in the candidate rule
                       all_syscalls_found=1
                       }
                done
                if [[ $all_syscalls_found -eq 0 ]]
                then
                    # We found a rule with all the syscall(s) we want; skip rest of macro
                    skip=0
                    break
                fi
                # Check if this rule can be grouped with our target syscall and keep track of it
                for syscall_g in "${syscall_grouping[@]}"
                do
                    if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                    then
                        file_to_edit=${audit_file}
                        rule_to_edit=${rule}
                        rule_syscalls_to_edit=${rule_syscalls}
                    fi
                done
            done
        else
            # If there is any candidate rule, it is compliant; skip rest of macro
            if [ "${#candidate_rules[@]}" -gt 0 ]
            then
                skip=0
            fi
        fi
        if [ "$skip" -eq 0 ]; then
            break
        fi
    done
    if [ "$skip" -ne 0 ]; then
        # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
        # At this point we know if we need to either append the $full_rule or group
        # the syscall together with an exsiting rule
        # Append the full_rule if it cannot be grouped to any other rule
        if [ -z ${rule_to_edit+x} ]
        then
            # Build full_rule while avoid adding double spaces when other_filters is empty
            if [ "${#syscall_a[@]}" -gt 0 ]
            then
                syscall_string=""
                for syscall in "${syscall_a[@]}"
                do
                    syscall_string+=" -S $syscall"
                done
            fi
            other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
            auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
            full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
            echo "$full_rule" >> "$default_file"
            chmod 0600 ${default_file}
        else
            # Check if the syscalls are declared as a comma separated list or
            # as multiple -S parameters
            if grep -q -- "," <<< "${rule_syscalls_to_edit}"
            then
                delimiter=","
            else
                delimiter=" -S "
            fi
            new_grouped_syscalls="${rule_syscalls_to_edit}"
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
                   # A syscall was not found in the candidate rule
                   new_grouped_syscalls+="${delimiter}${syscall}"
                   }
            done
            # Group the syscall in the rule
            sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
        fi
    fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | false | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_settimeofday
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_settimeofday
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for settimeofday for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - settimeofday
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of settimeofday in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_time_rules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - settimeofday
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of settimeofday in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_settimeofday
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Perform remediation of Audit rules for settimeofday for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - settimeofday
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of settimeofday in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_time_rules.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - settimeofday
      syscall_grouping:
      - adjtimex
      - settimeofday
      - stime
  - name: Check existence of settimeofday in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_time_rules
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.4.2.b
  - PCI-DSSv4-10.6
  - PCI-DSSv4-10.6.3
  - audit_rules_time_settimeofday
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
 | 
 | 
| | Rule  
                                Record Attempts to Alter Time Through stime
                                  [ref] |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_time_stime |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.4.2.b |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.6.3, 10.6 | 
 |  |  | 
 | 
| | Rule  
                                Record Attempts to Alter the localtime File
                                  [ref] |  | 
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:
 -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 lines to
 /etc/audit/audit.rules:
 -w /etc/localtime -p wa -k 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_time_watch_localtime |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.4.2.b |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.6.3, 10.6 | 
 |  |  | 
 | 
| | Rule  
                                Record Events that Modify the System's Network Environment
                                  [ref] |  | 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 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 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 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 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_networkconfig_modification |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.5.5 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.3.4, 10.3 | 
 |  | Remediation Shell script ⇲Remediation Ansible snippet ⇲# Remediation is applicable only in certain platforms
if rpm --quiet -q audit && rpm --quiet -q kernel || rpm --quiet -q kernel-uek; 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
	ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH"
	OTHER_FILTERS=""
	AUID_FILTERS=""
	SYSCALL="sethostname setdomainname"
	KEY="audit_rules_networkconfig_modification"
	SYSCALL_GROUPING="sethostname setdomainname"
	# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# 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
default_file="/etc/audit/rules.d/$KEY.rules"
# As other_filters may include paths, lets use a different delimiter for it
# The "F" script expression tells sed to print the filenames where the expressions matched
readarray -t files_to_inspect < <(sed -s -n -e "/^$ACTION_ARCH_FILTERS/!d" -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" -e "F" /etc/audit/rules.d/*.rules)
# 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 0600 "$file_to_inspect"
    fi
fi
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
	unset syscall_a
unset syscall_grouping
unset syscall_string
unset syscall
unset file_to_edit
unset rule_to_edit
unset rule_syscalls_to_edit
unset other_string
unset auid_string
unset full_rule
# Load macro arguments into arrays
read -a syscall_a <<< $SYSCALL
read -a syscall_grouping <<< $SYSCALL_GROUPING
# 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  |
# -----------------------------------------------------------------------------------------
#
files_to_inspect=()
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
default_file="/etc/audit/audit.rules"
files_to_inspect+=('/etc/audit/audit.rules' )
# After converting to jinja, we cannot return; therefore we skip the rest of the macro if needed instead
skip=1
for audit_file in "${files_to_inspect[@]}"
do
    # Filter existing $audit_file rules' definitions to select those that satisfy the rule pattern,
    # i.e, collect rules that match:
    # * the action, list and arch, (2-nd argument)
    # * the other filters, (3-rd argument)
    # * the auid filters, (4-rd argument)
    readarray -t similar_rules < <(sed -e "/^$ACTION_ARCH_FILTERS/!d"  -e "\#$OTHER_FILTERS#!d" -e "/$AUID_FILTERS/!d" "$audit_file")
    candidate_rules=()
    # Filter out rules that have more fields then required. This will remove rules more specific than the required scope
    for s_rule in "${similar_rules[@]}"
    do
        # Strip all the options and fields we know of,
        # than check if there was any field left over
        extra_fields=$(sed -E -e "s/^$ACTION_ARCH_FILTERS//"  -e "s#$OTHER_FILTERS##" -e "s/$AUID_FILTERS//" -e "s/((:?-S [[:alnum:],]+)+)//g" -e "s/-F key=\w+|-k \w+//"<<< "$s_rule")
        grep -q -- "-F" <<< "$extra_fields" || candidate_rules+=("$s_rule")
    done
    if [[ ${#syscall_a[@]} -ge 1 ]]
    then
        # Check if the syscall we want is present in any of the similar existing rules
        for rule in "${candidate_rules[@]}"
        do
            rule_syscalls=$(echo "$rule" | grep -o -P '(-S [\w,]+)+' | xargs)
            all_syscalls_found=0
            for syscall in "${syscall_a[@]}"
            do
                grep -q -- "\b${syscall}\b" <<< "$rule_syscalls" || {
                   # A syscall was not found in the candidate rule
                   all_syscalls_found=1
                   }
            done
            if [[ $all_syscalls_found -eq 0 ]]
            then
                # We found a rule with all the syscall(s) we want; skip rest of macro
                skip=0
                break
            fi
            # Check if this rule can be grouped with our target syscall and keep track of it
            for syscall_g in "${syscall_grouping[@]}"
            do
                if grep -q -- "\b${syscall_g}\b" <<< "$rule_syscalls"
                then
                    file_to_edit=${audit_file}
                    rule_to_edit=${rule}
                    rule_syscalls_to_edit=${rule_syscalls}
                fi
            done
        done
    else
        # If there is any candidate rule, it is compliant; skip rest of macro
        if [ "${#candidate_rules[@]}" -gt 0 ]
        then
            skip=0
        fi
    fi
    if [ "$skip" -eq 0 ]; then
        break
    fi
done
if [ "$skip" -ne 0 ]; then
    # We checked all rules that matched the expected resemblance pattern (action, arch & auid)
    # At this point we know if we need to either append the $full_rule or group
    # the syscall together with an exsiting rule
    # Append the full_rule if it cannot be grouped to any other rule
    if [ -z ${rule_to_edit+x} ]
    then
        # Build full_rule while avoid adding double spaces when other_filters is empty
        if [ "${#syscall_a[@]}" -gt 0 ]
        then
            syscall_string=""
            for syscall in "${syscall_a[@]}"
            do
                syscall_string+=" -S $syscall"
            done
        fi
        other_string=$([[ $OTHER_FILTERS ]] && echo " $OTHER_FILTERS") || /bin/true
        auid_string=$([[ $AUID_FILTERS ]] && echo " $AUID_FILTERS") || /bin/true
        full_rule="$ACTION_ARCH_FILTERS${syscall_string}${other_string}${auid_string} -F key=$KEY" || /bin/true
        echo "$full_rule" >> "$default_file"
        chmod 0600 ${default_file}
    else
        # Check if the syscalls are declared as a comma separated list or
        # as multiple -S parameters
        if grep -q -- "," <<< "${rule_syscalls_to_edit}"
        then
            delimiter=","
        else
            delimiter=" -S "
        fi
        new_grouped_syscalls="${rule_syscalls_to_edit}"
        for syscall in "${syscall_a[@]}"
        do
            grep -q -- "\b${syscall}\b" <<< "${rule_syscalls_to_edit}" || {
               # A syscall was not found in the candidate rule
               new_grouped_syscalls+="${delimiter}${syscall}"
               }
        done
        # Group the syscall in the rule
        sed -i -e "\#${rule_to_edit}#s#${rule_syscalls_to_edit}#${new_grouped_syscalls}#" "$file_to_edit"
    fi
fi
done
# Then perform the remediations for the watch rules
# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
files_to_inspect+=('/etc/audit/audit.rules')
# 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]+/etc/issue" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/issue $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 "wa" | 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\+/etc/issue$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 /etc/issue -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# 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/audit_rules_networkconfig_modification.rules' to list of files for inspection.
readarray -t matches < <(grep -HP "[\s]*-w[\s]+/etc/issue" /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/audit_rules_networkconfig_modification.rules' into list of files for inspection
    key_rule_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    # If the audit_rules_networkconfig_modification.rules file doesn't exist yet, create it with correct permissions
    if [ ! -e "$key_rule_file" ]
    then
        touch "$key_rule_file"
        chmod 0600 "$key_rule_file"
    fi
    files_to_inspect+=("$key_rule_file")
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]+/etc/issue" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/issue $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 "wa" | 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\+/etc/issue$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 /etc/issue -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
files_to_inspect+=('/etc/audit/audit.rules')
# 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]+/etc/issue.net" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/issue.net $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 "wa" | 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\+/etc/issue.net$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 /etc/issue.net -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# 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/audit_rules_networkconfig_modification.rules' to list of files for inspection.
readarray -t matches < <(grep -HP "[\s]*-w[\s]+/etc/issue.net" /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/audit_rules_networkconfig_modification.rules' into list of files for inspection
    key_rule_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    # If the audit_rules_networkconfig_modification.rules file doesn't exist yet, create it with correct permissions
    if [ ! -e "$key_rule_file" ]
    then
        touch "$key_rule_file"
        chmod 0600 "$key_rule_file"
    fi
    files_to_inspect+=("$key_rule_file")
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]+/etc/issue.net" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/issue.net $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 "wa" | 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\+/etc/issue.net$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 /etc/issue.net -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
files_to_inspect+=('/etc/audit/audit.rules')
# 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]+/etc/hosts" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/hosts $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 "wa" | 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\+/etc/hosts$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 /etc/hosts -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# 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/audit_rules_networkconfig_modification.rules' to list of files for inspection.
readarray -t matches < <(grep -HP "[\s]*-w[\s]+/etc/hosts" /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/audit_rules_networkconfig_modification.rules' into list of files for inspection
    key_rule_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    # If the audit_rules_networkconfig_modification.rules file doesn't exist yet, create it with correct permissions
    if [ ! -e "$key_rule_file" ]
    then
        touch "$key_rule_file"
        chmod 0600 "$key_rule_file"
    fi
    files_to_inspect+=("$key_rule_file")
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]+/etc/hosts" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/hosts $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 "wa" | 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\+/etc/hosts$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 /etc/hosts -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# into the list of files to be inspected
files_to_inspect+=('/etc/audit/audit.rules')
# 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]+/etc/sysconfig/network" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/sysconfig/network $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 "wa" | 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\+/etc/sysconfig/network$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 /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
# 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  |
# -----------------------------------------------------------------------------------------
files_to_inspect=()
# 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/audit_rules_networkconfig_modification.rules' to list of files for inspection.
readarray -t matches < <(grep -HP "[\s]*-w[\s]+/etc/sysconfig/network" /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/audit_rules_networkconfig_modification.rules' into list of files for inspection
    key_rule_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    # If the audit_rules_networkconfig_modification.rules file doesn't exist yet, create it with correct permissions
    if [ ! -e "$key_rule_file" ]
    then
        touch "$key_rule_file"
        chmod 0600 "$key_rule_file"
    fi
    files_to_inspect+=("$key_rule_file")
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]+/etc/sysconfig/network" "$audit_rules_file"
    then
        # Rule is found => verify yet if existing rule definition contains
        # all of the required access type bits
        # Define BRE whitespace class shortcut
        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\+/etc/sysconfig/network $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 "wa" | 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\+/etc/sysconfig/network$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 /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification" >> "$audit_rules_file"
    fi
done
else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
| Complexity: | low | 
|---|
 | Disruption: | low | 
|---|
 | Reboot: | false | 
|---|
 | Strategy: | restrict | 
|---|
 - name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Set architecture for audit tasks
  ansible.builtin.set_fact:
    audit_arch: b64
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
    == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Remediate audit rules for network configuration for 32bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - sethostname
      - setdomainname
      syscall_grouping:
      - sethostname
      - setdomainname
  - name: Check existence of sethostname, setdomainname in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_rules_networkconfig_modification
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - sethostname
      - setdomainname
      syscall_grouping:
      - sethostname
      - setdomainname
  - name: Check existence of sethostname, setdomainname in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F key=audit_rules_networkconfig_modification
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Remediate audit rules for network configuration for 64bit platform
  block:
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - sethostname
      - setdomainname
      syscall_grouping:
      - sethostname
      - setdomainname
  - name: Check existence of sethostname, setdomainname in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: '*.rules'
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Reset syscalls found per file
    ansible.builtin.set_fact:
      syscalls_per_file: {}
      found_paths_dict: {}
  - name: Declare syscalls found per file
    ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine( {item.files[0].path
      :[item.item] + syscalls_per_file.get(item.files[0].path, []) } ) }}"
    loop: '{{ find_command.results | selectattr(''matched'') | list }}'
  - name: Declare files where syscalls were found
    ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
      | flatten | map(attribute='path') | list }}"
  - name: Count occurrences of syscalls in paths
    ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({ item:1+found_paths_dict.get(item,
      0) }) }}"
    loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
      | list }}'
  - name: Get path with most syscalls
    ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() | sort(attribute='value')
      | last).key }}"
    when: found_paths | length >= 1
  - name: No file with syscall found, set path to /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.rules"
    when: found_paths | length == 0
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
        | join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_rules_networkconfig_modification
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  - name: Declare list of syscalls
    ansible.builtin.set_fact:
      syscalls:
      - sethostname
      - setdomainname
      syscall_grouping:
      - sethostname
      - setdomainname
  - name: Check existence of sethostname, setdomainname in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit
      contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+(( -S
        |,)\w+)* (-k\s+|-F\s+key=)\S+\s*$
      patterns: audit.rules
    register: find_command
    loop: '{{ (syscall_grouping + syscalls) | unique }}'
  - name: Set path to /etc/audit/audit.rules
    ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"
  - name: Declare found syscalls
    ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
      | map(attribute='item') | list }}"
  - name: Declare missing syscalls
    ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
      }}"
  - name: Replace the audit rule in {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found |
        join("|") }}))\b)((?:( -S |,)\w+)+)( (?:-k |-F key=)\w+)
      line: \1\2\3{{ missing_syscalls | join("\3") }}\4
      backrefs: true
      state: present
      mode: g-rwx,o-rwx
    when: syscalls_found | length > 0 and missing_syscalls | length > 0
  - name: Add the audit rule to {{ audit_file }}
    ansible.builtin.lineinfile:
      path: '{{ audit_file }}'
      line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F key=audit_rules_networkconfig_modification
      create: true
      mode: g-rwx,o-rwx
      state: present
    when: syscalls_found | length == 0
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - audit_arch == "b64"
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/issue already exists in /etc/audit/rules.d/
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
    for other rules with specified key audit_rules_networkconfig_modification
  ansible.builtin.find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use matched file
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/issue in /etc/audit/rules.d/
  ansible.builtin.lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/issue -p wa -k audit_rules_networkconfig_modification
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/issue already exists in /etc/audit/audit.rules
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/issue in /etc/audit/audit.rules
  ansible.builtin.lineinfile:
    line: -w /etc/issue -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/issue.net already exists in /etc/audit/rules.d/
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
    for other rules with specified key audit_rules_networkconfig_modification
  ansible.builtin.find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use matched file
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/issue.net in /etc/audit/rules.d/
  ansible.builtin.lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/issue.net already exists in /etc/audit/audit.rules
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/issue.net in /etc/audit/audit.rules
  ansible.builtin.lineinfile:
    line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/hosts already exists in /etc/audit/rules.d/
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
    for other rules with specified key audit_rules_networkconfig_modification
  ansible.builtin.find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use matched file
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/hosts in /etc/audit/rules.d/
  ansible.builtin.lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/hosts -p wa -k audit_rules_networkconfig_modification
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/hosts already exists in /etc/audit/audit.rules
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/hosts in /etc/audit/audit.rules
  ansible.builtin.lineinfile:
    line: -w /etc/hosts -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/sysconfig/network already exists in /etc/audit/rules.d/
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
    for other rules with specified key audit_rules_networkconfig_modification
  ansible.builtin.find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_modification$
    patterns: '*.rules'
  register: find_watch_key
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Use matched file
    as the recipient for the rule
  ansible.builtin.set_fact:
    all_files:
    - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - 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
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/sysconfig/network in /etc/audit/rules.d/
  ansible.builtin.lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Check if watch
    rule for /etc/sysconfig/network already exists in /etc/audit/audit.rules
  ansible.builtin.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:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: Record Events that Modify the System's Network Environment - Add watch rule
    for /etc/sysconfig/network in /etc/audit/audit.rules
  ansible.builtin.lineinfile:
    line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
    state: present
    dest: /etc/audit/audit.rules
    create: true
    mode: '0600'
  when:
  - '"audit" in ansible_facts.packages'
  - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
  - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
    == 0
  tags:
  - CJIS-5.4.1.1
  - NIST-800-171-3.1.7
  - NIST-800-53-AC-6(9)
  - NIST-800-53-AU-12(c)
  - NIST-800-53-AU-2(d)
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-10.5.5
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.4
  - audit_rules_networkconfig_modification
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
 | 
 | 
| | Rule  
                                Ensure auditd Collects System Administrator Actions
                                  [ref] |  | 
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:
 -w /etc/sudoers -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 lines to
 /etc/audit/audit.rules:
 -w /etc/sudoers -p wa -k actions 
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:
 -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 lines to
 /etc/audit/audit.rules:
 -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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_sysadmin_actions |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nist | AC-2(7)(b), AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.2, Req-10.2.5.b |  | os-srg | SRG-OS-000004-GPOS-00004, SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000062-GPOS-00031, SRG-OS-000304-GPOS-00121, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000470-GPOS-00214, SRG-OS-000471-GPOS-00215, SRG-OS-000239-GPOS-00089, SRG-OS-000240-GPOS-00090, SRG-OS-000241-GPOS-00091, SRG-OS-000303-GPOS-00120, SRG-OS-000304-GPOS-00121, SRG-OS-000466-GPOS-00210, SRG-OS-000476-GPOS-00221 |  | app-srg-ctr | SRG-APP-000026-CTR-000070, SRG-APP-000027-CTR-000075, SRG-APP-000028-CTR-000080, SRG-APP-000291-CTR-000675, SRG-APP-000292-CTR-000680, SRG-APP-000293-CTR-000685, SRG-APP-000294-CTR-000690, SRG-APP-000319-CTR-000745, SRG-APP-000320-CTR-000750, SRG-APP-000509-CTR-001305 |  | stigid | OL07-00-030700 |  | anssi | R73 |  | ism | 0582 |  | pcidss4 | 10.2.1.5, 10.2.1, 10.2 |  | stigref | SV-221810r958412_rule | 
 |  |  | 
 | 
| | Rule  
                                Record Events that Modify User/Group Information
                                  [ref] |  | 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
-w /etc/passwd -p wa -k audit_rules_usergroup_modification
-w /etc/gshadow -p wa -k audit_rules_usergroup_modification
-w /etc/shadow -p wa -k audit_rules_usergroup_modification
-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/group -p wa -k audit_rules_usergroup_modification
-w /etc/passwd -p wa -k audit_rules_usergroup_modification
-w /etc/gshadow -p wa -k audit_rules_usergroup_modification
-w /etc/shadow -p wa -k audit_rules_usergroup_modification
-w /etc/security/opasswd -p wa -k audit_rules_usergroup_modificationWarning: 
                                        This rule checks for multiple syscalls related to account changes;
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_usergroup_modification_groupaudit_rules_usergroup_modification_gshadowaudit_rules_usergroup_modification_passwd
 |  | 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. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_audit_rules_usergroup_modification |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.1.7 |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-004-6 R2.2.2, CIP-004-6 R2.2.3, CIP-007-3 R.1.3, CIP-007-3 R5, CIP-007-3 R5.1.1, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3 |  | nist | AC-2(4), AU-2(d), AU-12(c), AC-6(9), CM-6(a) |  | nist-csf | 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 |  | pcidss | Req-10.2.5 |  | os-srg | SRG-OS-000004-GPOS-00004, SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000239-GPOS-00089, SRG-OS-000241-GPOS-00090, SRG-OS-000241-GPOS-00091, SRG-OS-000303-GPOS-00120, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000476-GPOS-00221 |  | app-srg-ctr | SRG-APP-000026-CTR-000070, SRG-APP-000027-CTR-000075, SRG-APP-000028-CTR-000080, SRG-APP-000291-CTR-000675, SRG-APP-000292-CTR-000680, SRG-APP-000293-CTR-000685, SRG-APP-000294-CTR-000690, SRG-APP-000319-CTR-000745, SRG-APP-000320-CTR-000750, SRG-APP-000509-CTR-001305 | 
 |  |  | 
 | 
| Group  
                Configure auditd Data Retention
                          Group contains 6 rules | 
| [ref]  
                        The audit system writes data to  /var/log/audit/audit.log. By default,
 auditd rotates 5 logs by size (6MB), retaining a maximum of 30MB of
data in total, and refuses to write entries when the disk is too
full. This minimizes the risk of audit data filling its partition
and impacting other services. This also minimizes the risk of the audit
daemon temporarily disabling the system if it cannot write audit log (which
it can be configured to do).
For a busy
system or a system which is thoroughly auditing system activity, the default settings
for data retention may be
 insufficient. The log file size needed will depend heavily on what types
of events are being audited. First configure auditing to log all the events of
interest. Then monitor the log size manually for awhile to determine what file
size will allow you to keep the required data for the correct time period.
       
Using a dedicated partition for  /var/log/audit prevents the
 auditd logs from disrupting system functionality if they fill, and,
more importantly, prevents other activity in  /var from filling the
partition and stopping the audit trail. (The audit logs are size-limited and
therefore unlikely to grow without bound unless configured to do so.) Some
machines may have requirements that no actions occur which cannot be audited.
If this is the case, then  auditd can be configured to halt the machine
if it runs out of space. Note:  Since older logs are rotated,
configuring  auditd this way does not prevent older logs from being
rotated away before they can be viewed.
If your system is configured to halt when logging cannot be performed, make
sure this can never happen under normal circumstances! Ensure that /var/log/auditis on its own partition, and that this partition is
larger than the maximum amount of dataauditdwill retain
normally. | 
| | Rule  
                                Configure auditd flush priority
                                  [ref] |  | The  auditd service can be configured to
synchronously write audit event data to disk. Add or correct the following
line in  /etc/audit/auditd.conf to ensure that audit event data is
fully synchronized with the log files on the disk:
 flush = incremental_async
        |  | Rationale: | Audit data should be synchronously written to disk to ensure
log integrity. These parameters assure that all audit event data is fully
synchronized with the log files on the disk. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_data_retention_flush |  | References: | | cis-csc | 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9 |  | cobit5 | APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, BAI03.05, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01 |  | cui | 3.3.1 |  | hipaa | 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) |  | isa-62443-2009 | 4.3.2.6.7, 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 |  | isa-62443-2013 | SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2 |  | iso27001-2013 | A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2 |  | nerc-cip | CIP-004-6 R2.2.3, CIP-004-6 R3.3, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, CIP-007-3 R6.5 |  | nist | AU-11, CM-6(a) |  | nist-csf | DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.PT-1 |  | ospp | FAU_GEN.1 |  | os-srg | SRG-OS-000480-GPOS-00227 |  | ism | 0582 | 
 |  |  | 
 | 
| | Rule  
                                Set number of records to cause an explicit flush to audit logs
                                  [ref] |  | To configure Audit daemon to issue an explicit flush to disk command
after writing 50  records, set  freq to  50
in  /etc/audit/auditd.conf. |  | Rationale: | If option  freq isn't set to  50, the flush to disk
may happen after higher number of records, increasing the danger
of audit loss. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_freq |  | References: |  |  |  | 
 | 
| | Rule  
                                Include Local Events in Audit Logs
                                  [ref] |  | To configure Audit daemon to include local events in Audit logs, set
local_eventstoyesin/etc/audit/auditd.conf.
This is the default setting. |  | Rationale: | If option local_eventsisn't set toyesonly events from
network will be aggregated. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_local_events |  | References: | | nist | CM-6 |  | os-srg | SRG-OS-000062-GPOS-00031, SRG-OS-000480-GPOS-00227 |  | ism | 0582 | 
 |  |  | 
 | 
| | Rule  
                                Resolve information before writing to audit logs
                                  [ref] |  | To configure Audit daemon to resolve all uid, gid, syscall,
architecture, and socket address information before writing the
events to disk, set log_formattoENRICHEDin/etc/audit/auditd.conf. |  | Rationale: | If option log_formatisn't set toENRICHED, the
audit records will be stored in a format exactly as the kernel sends them. |  | Severity: | low |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_log_format |  | References: | | nist | CM-6, AU-3 |  | ospp | FAU_GEN.1.2 |  | os-srg | SRG-OS-000255-GPOS-00096, SRG-OS-000480-GPOS-00227 |  | app-srg-ctr | SRG-APP-000096-CTR-000175, SRG-APP-000097-CTR-000180, SRG-APP-000098-CTR-000185, SRG-APP-000099-CTR-000190, SRG-APP-000100-CTR-000195, SRG-APP-000100-CTR-000200, SRG-APP-000109-CTR-000215, SRG-APP-000290-CTR-000670, SRG-APP-000357-CTR-000800 |  | ism | 0582 | 
 |  |  | 
 | 
| | Rule  
                                Set type of computer node name logging in audit logs
                                  [ref] |  | To configure Audit daemon to use a unique identifier
as computer node name in the audit events,
set  name_format to  hostname
in  /etc/audit/auditd.conf.Warning: 
                                        Whenever the variable  var_auditd_name_format  uses a multiple value option, for example
 A|B|C , the first value will be used when remediating this rule. |  | Rationale: | If option name_formatis left at its default value ofnone, audit events from different computers may be hard
to distinguish. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_name_format |  | References: | | nist | CM-6, AU-3 |  | ospp | FAU_GEN.1.2 |  | os-srg | SRG-OS-000039-GPOS-00017, SRG-OS-000342-GPOS-00133, SRG-OS-000479-GPOS-00224 |  | stigid | OL07-00-030211 |  | ism | 0582 |  | pcidss4 | 10.2.2, 10.2 |  | stigref | SV-221769r958754_rule | 
 |  |  | 
 | 
| | Rule  
                                Write Audit Logs to the Disk
                                  [ref] |  | To configure Audit daemon to write Audit logs to the disk, set
write_logstoyesin/etc/audit/auditd.conf.
This is the default setting. |  | Rationale: | If write_logsisn't set toyes, the Audit logs will
not be written to the disk. |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_auditd_write_logs |  | References: |  |  |  | 
 | 
| | Rule  
                                Enable auditd Service
                                  [ref] |  | 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 auditdservice is active ensures audit records
generated by the kernel are appropriately recorded.
 Additionally, a properly configured audit subsystem ensures that actions of
individual system users can be uniquely traced to those users so they
can be held accountable for their actions.
 |  | Severity: | medium |  | Rule ID: | xccdf_org.ssgproject.content_rule_service_auditd_enabled |  | References: | | cis-csc | 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9 |  | cjis | 5.4.1.1 |  | cobit5 | 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 |  | cui | 3.3.1, 3.3.2, 3.3.6 |  | hipaa | 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) |  | isa-62443-2009 | 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 |  | isa-62443-2013 | 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 |  | iso27001-2013 | 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 |  | nerc-cip | CIP-004-6 R3.3, CIP-007-3 R6.5 |  | nist | AC-2(g), AU-3, AU-10, AU-2(d), AU-12(c), AU-14(1), AC-6(9), CM-6(a), SI-4(23) |  | nist-csf | 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 |  | ospp | FAU_GEN.1 |  | pcidss | Req-10.1 |  | os-srg | SRG-OS-000062-GPOS-00031, SRG-OS-000037-GPOS-00015, SRG-OS-000038-GPOS-00016, SRG-OS-000039-GPOS-00017, SRG-OS-000040-GPOS-00018, SRG-OS-000041-GPOS-00019, SRG-OS-000042-GPOS-00021, SRG-OS-000051-GPOS-00024, SRG-OS-000054-GPOS-00025, SRG-OS-000122-GPOS-00063, SRG-OS-000254-GPOS-00095, SRG-OS-000255-GPOS-00096, SRG-OS-000337-GPOS-00129, SRG-OS-000348-GPOS-00136, SRG-OS-000349-GPOS-00137, SRG-OS-000350-GPOS-00138, SRG-OS-000351-GPOS-00139, SRG-OS-000352-GPOS-00140, SRG-OS-000353-GPOS-00141, SRG-OS-000354-GPOS-00142, SRG-OS-000358-GPOS-00145, SRG-OS-000365-GPOS-00152, SRG-OS-000392-GPOS-00172, SRG-OS-000475-GPOS-00220 |  | app-srg-ctr | SRG-APP-000095-CTR-000170, SRG-APP-000409-CTR-000990, SRG-APP-000508-CTR-001300, SRG-APP-000510-CTR-001310 |  | stigid | OL07-00-030000 |  | anssi | R33, R73 |  | ism | 1409 |  | pcidss4 | 10.2.1, 10.2 |  | stigref | SV-221764r1015189_rule | 
 |  |  | 
 |