$rcTrue = "True" $rcCompliant = "Compliant" $rcFalse = "False" $rcNone = "None" $rcNonCompliant = "Non-Compliant" $rcNonCompliantManualReviewRequired = "Manual review required" $rcCompliantIPv6isDisabled = "IPv6 is disabled" $retCompliant = @{ Message = $rcCompliant Status = $rcTrue } $retNonCompliant = @{ Message = $rcNonCompliant Status = $rcFalse } $retCompliantIPv6Disabled = @{ Message = $rcCompliantIPv6isDisabled Status = $rcTrue } $retNonCompliantManualReviewRequired = @{ Message = $rcNonCompliantManualReviewRequired Status = $rcNone } $IPv6Status_script = grep -Pqs '^\h*0\b' /sys/module/ipv6/parameters/disable && echo "IPv6 is enabled" || echo "IPv6 is not enabled" $IPv6Status = bash -c $IPv6Status_script if ($IPv6Status -match "is enabled") { $IPv6Status = "enabled" } else { $IPv6Status = "disabled" } $parentPath = Split-Path -Parent -Path $PSScriptRoot $scriptPath = $parentPath + "/Helpers/ShellScripts/RHEL9/" ### Chapter 1 - Initial Setup [AuditTest] @{ Id = "1.1.1.1" Task = "Ensure mounting of squashfs filesystems is disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_1111.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.1.2" Task = "Ensure mounting of udf filesystems is disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_1112.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.2.1" Task = "Ensure /tmp is a separate partition" Test = { $result = findmnt --kernel /tmp | grep -E '\s/tmp\s' if ($result -match "/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.2.2" Task = "Ensure nodev option set on /tmp partition" Test = { $result = findmnt --kernel /tmp | grep nodev if ($result -match "/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.2.3" Task = "Ensure noexec option set on /tmp partition" Test = { $result = findmnt --kernel /tmp | grep noexec if ($result -match "/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.2.4" Task = "Ensure nosuid option set on /tmp partition" Test = { $result = findmnt --kernel /tmp | grep nosuid if ($result -match "/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.3.1" Task = "Ensure separate partition exists for /var" Test = { $result = findmnt --kernel /var if ($result -match "/var") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.3.2" Task = "Ensure nodev option set on /var partition" Test = { $result = findmnt --kernel /var | grep nodev if ($result -match "/var") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.3.3" Task = "Ensure nosuid option set on /var partition" Test = { $result = findmnt --kernel /var | grep nosuid if ($result -match "/var") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.4.1" Task = "Ensure separate partition exists for /var/tmp" Test = { $result = findmnt --kernel /var/tmp if ($result -match "/var/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.4.2" Task = "Ensure noexec option set on /var/tmp partition" Test = { $result = findmnt --kernel /var/tmp | grep noexec if ($result -match "/var/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.4.3" Task = "Ensure nosuid option set on /var/tmp partition" Test = { $result = findmnt --kernel /var/tmp | grep nosuid if ($result -match "/var/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.4.4" Task = "Ensure nodev option set on /var/tmp partition" Test = { $result = findmnt --kernel /var/tmp | grep nodev if ($result -match "/tmp") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.5.1" Task = "Ensure separate partition exists for /var/log" Test = { $result = findmnt --kernel /var/log if ($result -match "/var/log") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.5.2" Task = "Ensure nodev option set on /var/log" Test = { $result = findmnt --kernel /var/log | grep nodev if ($result -match "/var/log") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.5.3" Task = "Ensure noexec option set on /var/log" Test = { $result = findmnt --kernel /var/log | grep noexec if ($result -match "/var/log") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.5.4" Task = "Ensure nosuid option set on /var/log" Test = { $result = findmnt --kernel /var/log | grep nosuid if ($result -match "/var/log") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.6.1" Task = "Ensure separate partition exists for /var/log/audit" Test = { $result = findmnt --kernel /var/log/audit if ($result -match "/var/log/audit") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.6.2" Task = "Ensure noexec option set on /var/log/audit" Test = { $result = findmnt --kernel /var/log/audit | grep noexec if ($result -match "/var/log/audit") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.6.3" Task = "Ensure nodev option set on /var/log/audit" Test = { $result = findmnt --kernel /var/log/audit | grep nodev if ($result -match "/var/log/audit") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.6.4" Task = "Ensure nosuid option set on /var/log/audit" Test = { $result = findmnt --kernel /var/log/audit | grep nosuid if ($result -match "/var/log/audit") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.7.1" Task = "Ensure separate partition exists for /home" Test = { $result = findmnt --kernel /home if ($result -match "/home") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.7.2" Task = "Ensure nodev option set on /home" Test = { $result = findmnt --kernel /home | grep nodev if ($result -match "/home") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.7.3" Task = "Ensure nosuid option set on /home" Test = { $result = findmnt --kernel /home | grep nosuid if ($result -match "/home") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.8.1" Task = "Ensure /dev/shm is a separate partition" Test = { $result = findmnt --kernel /dev/shm if ($result -match "/dev/shm") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.8.2" Task = "Ensure nodev option set on /dev/shm partition" Test = { $result = mount | grep -E '\s/dev/shm\s' | grep nodev if ($result -match "/dev/shm") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.8.3" Task = "Ensure noexec option set on /dev/shm partition" Test = { $result = findmnt --kernel /dev/shm | grep noexec if ($result -match "/dev/shm") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.8.4" Task = "Ensure nosuid option set on /dev/shm partition" Test = { $result = findmnt --kernel /dev/shm | grep nosuid if ($result -match "/dev/shm") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.1.9" Task = "Disable USB Storage" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_119.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.2.1" Task = "Ensure GPG keys are configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "1.2.2" Task = "Ensure gpgcheck is globally activated" Test = { $result = grep ^gpgcheck /etc/dnf/dnf.conf if ($result -match "gpgcheck=1") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.2.3" Task = "Ensure package manager repositories are configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "1.2.4" Task = "Ensure repo_gpgcheck is globally activated" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "1.3.1" Task = "Ensure aide is installed" Test = { $result = rpm -q aide if ($result -match "aide-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.3.2" Task = "Ensure filesystem integrity is regularly checked" Test = { $result1 = systemctl is-enabled aidecheck.service $result2 = systemctl is-enabled aidecheck.timer $result3 = systemctl status aidecheck.service if ($result1 -match "enabled" -and $result2 -match "enabled" -and $result3 -match "Active:") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.3.3" Task = "Ensure filesystem integrity is regularly checked" Test = { $result = grep -Ps -- '(\/sbin\/(audit|au)\H*\b)' /etc/aide.conf.d/*.conf /etc/aide.conf if ($result -match "/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512" -and $result -match "/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512" -and $result -match "/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512" -and $result -match "/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512" -and $result -match "/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512" -and $result -match "/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512"){ return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.4.1" Task = "Ensure bootloader password is set" Test = { $result = awk -F. '/^\s*GRUB2_PASSWORD/ {print $1"."$2"."$3}' /boot/grub2/user.cfg if ($result -match "GRUB2_PASSWORD=grub.pbkdf2.sha512") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.4.2" Task = "Ensure permissions on bootloader config are configured" Test = { $result1 = stat -Lc "%n %#a %u/%U %g/%G" /boot/grub2/grub.cfg | grep '/boot/grub2/grub.cfg\s*0700\s*0/root\s*0/root' $result2 = stat -Lc "%n %#a %u/%U %g/%G" /boot/grub2/grubenv | grep '/boot/grub2/grubenv\s*0600\s*0/root\s*0/root' $result3 = stat -Lc "%n %#a %u/%U %g/%G" /boot/grub2/user.cfg | grep '/boot/grub2/user.cfg\s*0600\s*0/root\s*0/root' if ($result1 -ne $null -and $result2 -ne $null -and $result3 -ne $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.5.1" Task = "Ensure core dump storage is disabled" Test = { $result = grep -i '^\s*storage\s*=\s*none' /etc/systemd/coredump.conf if ($result -match "Storage=none") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.5.2" Task = "Ensure core dump backtraces are disabled" Test = { $script_string = @' #!/usr/bin/env bash { grep -Pi '^\h*ProcessSizeMax\h*=\h*0\b' /etc/systemd/coredump.conf || echo -e "\n- Audit results:\n FAIL\n - \"ProcessSizeMax\" is: \"$(grep -i 'ProcessSizeMax' /etc/systemd/coredump.conf)\"" } '@ $result = bash -c $script_string if ($result -match "FAIL") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "1.5.3" Task = "Ensure address space layout randomization (ASLR) is enabled" Test = { $script_string = @' #!/usr/bin/env bash { l_output="" l_output2="" l_parlist="kernel.randomize_va_space=2" l_searchloc="/run/sysctl.d/*.conf /etc/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /lib/sysctl.d/*.conf /etc/sysctl.conf $([ -f /etc/default/ufw ] && awk -F= '/^\s*IPT_SYSCTL=/ {print $2}' /etc/default/ufw)" KPC() { l_krp="$(sysctl "$l_kpname" | awk -F= '{print $2}' | xargs)" l_pafile="$(grep -Psl -- "^\h*$l_kpname\h*=\h*$l_kpvalue\b\h*(#.*)?$" $l_searchloc)" l_fafile="$(grep -s -- "^\s*$l_kpname" $l_searchloc | grep -Pv -- "\h*=\h*$l_kpvalue\b\h*" | awk -F: '{print $1}')" if [ "$l_krp" = "$l_kpvalue" ]; then l_output="$l_output\n - \"$l_kpname\" is set to \"$l_kpvalue\" in the running configuration" else l_output2="$l_output2\n - \"$l_kpname\" is set to \"$l_krp\" in the running configuration" fi if [ -n "$l_pafile" ]; then l_output="$l_output\n - \"$l_kpname\" is set to \"$l_kpvalue\" in \"$l_pafile\"" else l_output2="$l_output2\n - \"$l_kpname = $l_kpvalue\" is not set in a kernel parameter configuration file" fi [ -n "$l_fafile" ] && l_output2="$l_output2\n - \"$l_kpname\" is set incorrectly in \"$l_fafile\"" } for l_kpe in $l_parlist; do l_kpname="$(awk -F= '{print $1}' <<< "$l_kpe")" l_kpvalue="$(awk -F= '{print $2}' <<< "$l_kpe")" KPC done if [ -z "$l_output2" ]; then echo -e "\n- Audit Result:\n PASS\n$l_output\n" else echo -e "\n- Audit Result:\n FAIL\n - Reason(s) for audit failure:\n$l_output2\n" [ -n "$l_output" ] && echo -e "\n- Correctly set:\n$l_output\n" fi } '@ $script = bash -c $script_string if ($script -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.1" Task = "Ensure SELinux is installed" Test = { $result = rpm -q libselinux if ($result -match "libselinux-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.2" Task = "Ensure SELinux is not disabled in bootloader configuration" Test = { $result = grubby --info=ALL | grep -Po '(selinux|enforcing)=0\b' if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.3" Task = "Ensure SELinux policy is configured" Test = { $result1 = grep -E '^\s*SELINUXTYPE=(targeted|mls)\b' /etc/selinux/config $result2 = sestatus | grep Loaded if (($result1 -match "targeted" -or $result1 -match "mls") -and ($result2 -match "targeted" -or $result2 -match "mls")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.4" Task = "Ensure the SELinux mode is not disabled" Test = { $result1 = getenforce $result2 = grep -Ei '^\s*SELINUX=(enforcing|permissive)' /etc/selinux/config if (($result1 -match "Enforcing" -or $result1 -match "Permissive") -and ($result2 -match "SELINUX=enforcing" -or $result2 -match "SELINUX=permissive")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.5" Task = "Ensure the SELinux mode is enforcing" Test = { $result1 = getenforce $result2 = grep -i SELINUX=enforcing /etc/selinux/config if ($result1 -match "Enforcing" -and $result2 -match "SELINUX=enforcing") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.6" Task = "Ensure no uncofined services exist" Test = { $result = ps -eZ | grep unconfined_service_t if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.7" Task = "Ensure SETroubleshoot is not installed" Test = { $result = rpm -q setroubleshoot if ($result -match "is not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.6.1.8" Task = "Ensure the MCS Translation Service (mcstrans) is not installed" Test = { $result = rpm -q mcstrans if ($result -match "is not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.1" Task = "Ensure the MCS Translation Service (mcstrans) is not installed" Test = { $result = grep -E -i "(\\\v|\\\r|\\\m|\\\s|$(grep '^ID=' /etc/os-release | cut -d= -f2 | sed -e 's/"//g'))" /etc/motd if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.2" Task = "Ensure local login warning banner is configured properly" Test = { $result = grep -E -i "(\\\v|\\\r|\\\m|\\\s|$(grep '^ID=' /etc/os-release | cut -d= -f2 | sed -e 's/"//g'))" /etc/issue if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.3" Task = "Ensure remote login warning banner is configured properly" Test = { $result = grep -E -i "(\\\v|\\\r|\\\m|\\\s|$(grep '^ID=' /etc/os-release | cut -d= -f2 | sed -e 's/"//g'))" /etc/issue.net if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.4" Task = "Ensure permissions on /etc/motd are configured" Test = { $result = stat -c "%a" /etc/motd if ($result -eq 644) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.5" Task = "Ensure permissions on /etc/issue are configured" Test = { $result = stat -c "%a" /etc/issue if ($result -eq 644) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.7.6" Task = "Ensure permissions on /etc/issue.net are configured" Test = { $result = stat -c "%a" /etc/issue.net if ($result -eq 644) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.1" Task = "Ensure GNOME Display Manager is removed" Test = { $result = rpm -q gdm if ($result -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.2" Task = "Ensure GDM login banner is configured" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_182.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.3" Task = "Ensure GDM disable-user-list option is enabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_183.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.4" Task = "Ensure GDM screen locks then the user is idle" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_184.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.5" Task = "Ensure GDM screen locks cannot be overridden" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_185.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.6" Task = "Ensure GDM automatic mounting of removable media is disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_186.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.7" Task = "Ensure GDM disabling automatic mounting of removable media is not overridden" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_187.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.8" Task = "Ensure GDM autorun-never is enabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_188.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.9" Task = "Ensure GDM autorun-never is not overridden" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_189.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.8.10" Task = "Ensure XDCMP is not enabled" Test = { $test = grep -Eis '^\s*Enable\s*=\s*true' /etc/gdm/custom.conf if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "1.9" Task = "Ensure updates, patches, and additional security software are installed" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "1.10" Task = "Ensure system-wide crypto policy is not legacy" Test = { $test = grep -E -i '^\s*LEGACY\s*(\s+#.*)?$' /etc/crypto-policies/config if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } ### Chapter 2 - Services [AuditTest] @{ Id = "2.1.1" Task = "Ensure time synchronization is in use" Test = { $test = rpm -q chrony if ($test -match "chrony-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.1.2" Task = "Ensure chrony is configured" Test = { $test = grep -E "^(server|pool)" /etc/chrony.conf | grep OPTIONS\s*-u\s*chrony if ($test -match "OPTIONS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.1" Task = "Ensure xorg-x11-server-common is not installed" Test = { $test = rpm -q xorg-x11-server-common if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.2" Task = "Ensure Avahi Server is not installed" Test = { $test = rpm -q avahi if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.3" Task = "Ensure CUPS is not installed" Test = { $test = rpm -q cups if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.4" Task = "Ensure DHCP Server is not installed" Test = { $test = rpm -q dhcp-server if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.5" Task = "Ensure DNS Server is not installed" Test = { $test = rpm -q bind if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.6" Task = "Ensure VSFTP Server is not installed" Test = { $test = rpm -q vsftpd if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.7" Task = "Ensure VSFTP Server is not installed" Test = { $test = rpm -q vsftpd if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.8" Task = "Ensure a web server is not installed" Test = { $test = rpm -q httpd nginx if ($test -match "httpd is not installed" -and $test -match "nginx is not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.9" Task = "Ensure IMAP and POP3 server is not installed" Test = { $test = rpm -q dovecot cyrus-imapd if ($test -match "dovecot is not installed" -and $test -match "cyrus-imapd is not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.10" Task = "Ensure Samba is not installed" Test = { $test = rpm -q samba if ($test -match "samba is not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.11" Task = "Ensure HTTP Proxy Server is not installed" Test = { $test = rpm -q squid if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.12" Task = "Ensure net-snmp is not installed" Test = { $test = rpm -q net-snmp if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.13" Task = "Ensure telnet-server is not installed" Test = { $test = rpm -q telnet-server if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.14" Task = "Ensure dnsmasq is not installed" Test = { $test = rpm -q dnsmasq if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.15" Task = "Ensure mail transfer agent is configured for local-only mode" Test = { $test = ss -lntu | grep -E ':25\s' | grep -E -v '\s(127.0.0.1|\[?::1\]?):25\s' if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.16" Task = "Ensure nfs-utils is not installed or the nfs-server service is masked" Test = { rpm -q nfs-utils if ($?) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.17" Task = "Ensure rpcbind is not installed or the rpcbind services are masked" Test = { $test1 = rpm -q rpcbind $test21 = systemctl is-enabled rpcbind $test22 = systemctl is-enabled rpcbind.socket if ($test1 -match "not installed" -or ($test21 -match "masked" -and $test22 -match "masked")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.2.18" Task = "Ensure rsync-daemon is not installed or the rsyncd service is masked" Test = { $test1 = rpm -q rsync-daemon $test2 = systemctl is-enabled rsync-daemon if ($test1 -match "not installed" -or $test2 -match "masked") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.3.1" Task = "Ensure telnet client is not installed" Test = { $test = rpm -q telnet if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.3.2" Task = "Ensure LDAP client is not installed" Test = { $test = rpm -q openldap-clients if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.3.3" Task = "Ensure TFTP client is not installed" Test = { $test = rpm -q tftp if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.3.4" Task = "Ensure FTP client is not installed" Test = { $test = rpm -q ftp if ($test -match "not installed") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "2.4" Task = "Ensure nonessential services listening on the system are removed or masked" Test = { return $retNonCompliantManualReviewRequired } } ### Chapter 3 - Network Configuration [AuditTest] @{ Id = "3.1.1" Task = "Ensure IPv6 status is identified" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "3.1.2" Task = "Ensure wireless interfaces are disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_312.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.1.3" Task = "Ensure TIPC is disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_313.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.2.1" Task = "Ensure IP forwarding is disabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_321.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.2.2" Task = "Ensure packet redirect sending is disabled" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_322_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_322_2.sh" $result2 = bash $resultScript2 if ($result1 -match "PASS" -and $result2 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.1" Task = "Ensure packet redirect sending is disabled" Test = { $resultScript11 = $scriptPath + "CIS100_RHEL9_331_11.sh" $result11 = bash $resultScript11 $resultScript12 = $scriptPath + "CIS100_RHEL9_331_12.sh" $result12 = bash $resultScript12 $resultScript21 = $scriptPath + "CIS100_RHEL9_331_21.sh" $result21 = bash $resultScript21 $resultScript22 = $scriptPath + "CIS100_RHEL9_331_22.sh" $result22 = bash $resultScript22 if ($IPv6Status -eq "enabled") { if ($result21 -match "PASS" -and $result22 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } else { if ($result11 -match "PASS" -and $result12 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } } [AuditTest] @{ Id = "3.3.2" Task = "Ensure ICMP redirects are not accepted" Test = { $resultScript11 = $scriptPath + "CIS100_RHEL9_332_11.sh" $result11 = bash $resultScript11 $resultScript12 = $scriptPath + "CIS100_RHEL9_332_12.sh" $result12 = bash $resultScript12 $resultScript21 = $scriptPath + "CIS100_RHEL9_332_21.sh" $result21 = bash $resultScript21 $resultScript22 = $scriptPath + "CIS100_RHEL9_332_22.sh" $result22 = bash $resultScript22 if ($IPv6Status -eq "enabled") { if ($result21 -match "PASS" -and $result22 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } else { if ($result11 -match "PASS" -and $result12 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } } # 3.3.3 ist identisch mit 3.3.2 ... warum auch immer - wird hier weg gelassen [AuditTest] @{ Id = "3.3.4" Task = "Ensure suspicious packets are logged" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_334_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_334_2.sh" $result2 = bash $resultScript2 if ($result1 -match "PASS" -and $result2 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.5" Task = "Ensure broadcast ICMP requests are ignored" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_335.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.6" Task = "Ensure bogus ICMP responses are ignored" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_336.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.7" Task = "Ensure Reverse Path Filtering is enabled" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_337_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_337_2.sh" $result2 = bash $resultScript2 if ($result1 -match "PASS" -and $result2 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.8" Task = "Ensure TCP SYN Cookies is enabled" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_338.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.3.9" Task = "Ensure IPv6 router advertisements are not accepted" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_339_1.sh" $resultScript1 = $scriptPath + "CIS100_RHEL9_339_2.sh" if ($IPv6Status -match "disabled") { return $retCompliantIPv6Disabled } else { $script1 = bash $resultScript1 $script2 = bash $resultScript2 if ($script1 -match "PASS" -and $script2 -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } } [AuditTest] @{ Id = "3.4.1.1" Task = "Ensure nftables is installed" Test = { $result = rpm -q nftables if ($result -match "nftables-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.4.1.2" Task = "Ensure a single firewall configuration utility is in use" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_3412.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.4.2.1" Task = "Ensure firewalld default zone is set" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_3421.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.4.2.2" Task = "Ensure at least one nftables table exists" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "3.4.2.3" Task = "Ensure nftables base chains exist" Test = { try{ $test1 = nft list ruleset | grep 'hook input' $test2 = nft list ruleset | grep 'hook forward' $test3 = nft list ruleset | grep 'hook output' if($test1 -match "type filter hook input" -and $test2 -match "type filter hook forward" -and $test3 -match "type filter hook output"){ return @{ Message = "Compliant" Status = "True" } } return @{ Message = "Not-Compliant" Status = "False" } } catch{ return @{ Message = "Command not found!" Status = "False" } } } } [AuditTest] @{ Id = "3.4.2.4" Task = "Ensure host based firewall loopback traffic is configured" Test = { $script_string = @' #!/usr/bin/env bash { l_output="" l_output2="" if nft list ruleset | awk '/hook\s+input\s+/,/\}\s*(#.*)?$/' | grep -Pq -- '\H+\h+"lo"\h+accept'; then l_output="$l_output\n - Network traffic to the loopback address is correctly set to accept" else l_output2="$l_output2\n - Network traffic to the loopback address is not set to accept" fi l_ipsaddr="$(nft list ruleset | awk '/filter_IN_public_deny|hook\s+input\s+/,/\}\s*(#.*)?$/' | grep -P -- 'ip\h+saddr')" if grep -Pq -- 'ip\h+saddr\h+127\.0\.0\.0\/8\h+(counter\h+packets\h+\d+\h+bytes\h+\d+\h+)?drop' <<< "$l_ipsaddr" || grep -Pq -- 'ip\h+daddr\h+\!\=\h+127\.0\.0\.1\h+ip\h+saddr\h+127\.0\.0\.1\h+drop' <<< "$l_ipsaddr"; then l_output="$l_output\n - IPv4 network traffic from loopback address correctly set to drop" else l_output2="$l_output2\n - IPv4 network traffic from loopback address not set to drop" fi if grep -Pq -- '^\h*0\h*$' /sys/module/ipv6/parameters/disable; then l_ip6saddr="$(nft list ruleset | awk '/filter_IN_public_deny|hook input/,/}/' | grep 'ip6 saddr')" if grep -Pq 'ip6\h+saddr\h+::1\h+(counter\h+packets\h+\d+\h+bytes\h+\d+\h+)?drop' <<< "$l_ip6saddr" || grep -Pq -- 'ip6\h+daddr\h+\!=\h+::1\h+ip6\h+saddr\h+::1\h+drop' <<< "$l_ip6saddr"; then l_output="$l_output\n - IPv6 network traffic from loopback address correctly set to drop" else l_output2="$l_output2\n - IPv6 network traffic from loopback address not set to drop" fi fi if [ -z "$l_output2" ]; then echo -e "\n- Audit Result:\n PASS\n$l_output" else echo -e "\n- Audit Result:\n FAIL\n$l_output2\n\n - Correctly set:\n$l_output" fi } '@ $script = bash -c $script_string if ($script -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "3.4.2.5" Task = "Ensure firewalld drops unnecessary services and ports" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "3.4.2.6" Task = "Ensure nftables established connections are configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "3.4.2.7" Task = "Ensure nftables default deny firewall policy" Test = { $result1 = systemctl --quiet is-enabled nftables.service && nft list ruleset | grep 'hook input' | grep -v 'policy drop' $result2 = systemctl --quiet is-enabled nftables.service && nft list ruleset | grep 'hook forward' | grep -v 'policy drop' if ($result1 -eq $null -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } ### Chapter 4 - Logging and Auditing [AuditTest] @{ Id = "4.1.1.1" Task = "Ensure auditd is installed" Test = { $result1 = rpm -q audit if ($result1 -match "audit-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.1.2" Task = "Ensure auditing for processes that start prior to auditd is enabled" Test = { $result1 = grubby --info=ALL | grep -Po '\baudit=1\b' if ($result1 -match "audit=1") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.1.3" Task = "Ensure audit_backlog_limit is sufficient" Test = { $result1 = grubby --info=ALL | grep -Po "\baudit_backlog_limit=\d+\b" if ($result1 -match "audit_backlog_limit=") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.1.4" Task = "Ensure auditd service is enabled" Test = { $result1 = systemctl is-enabled auditd if ($result1 -match "enabled") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.2.1" Task = "Ensure audit log storage size is configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.1.2.2" Task = "Ensure audit logs are not automatically deleted" Test = { $result1 = grep max_log_file_action /etc/audit/auditd.conf | grep max_log_file_action if ($result1 -match "max_log_file_action = keep_logs") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.2.3" Task = "Ensure system is disabled when audit logs are full" Test = { $result1 = grep space_left_action /etc/audit/auditd.conf $result2 = grep action_mail_acct /etc/audit/auditd.conf $result3 = grep -E 'admin_space_left_action\s*=\s*(halt|single)' /etc/audit/auditd.conf if ($result1 -match "space_left_action = email" -and $result2 -match "action_mail_acct = root" -and ($result3 -match "admin_space_left_action = halt" -or $result3 -match "admin_space_left_action = single")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.1" Task = "Ensure changes to system administration scope (sudoers) is collected" Test = { $result1 = awk '/^ *-w/ &&/\/etc\/sudoers/ &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules $result2 = auditctl -l | awk '/^ *-w/ &&/\/etc\/sudoers/ &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' if ($result1 -match "-w /etc/sudoers -p wa -k scope" -and $result1 -match "-w /etc/sudoers.d -p wa -k scope" -and $result2 -match "-w /etc/sudoers -p wa -k scope" -and $result2 -match "-w /etc/sudoers.d -p wa -k scope") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.2" Task = "Ensure actions as another user are always logged" Test = { $result1 = awk '/^ *-a *always,exit/ &&/ -F *arch=b[2346]{2}/ &&(/ -F *auid!=unset/||/ -F *auid!=-1/||/ -F *auid!=4294967295/) &&(/ -C *euid!=uid/||/ -C *uid!=euid/) &&/ -S *execve/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules $result2 = auditctl -l | awk '/^ *-a *always,exit/ &&/ -F *arch=b[2346]{2}/ &&(/ -F *auid!=unset/||/ -F *auid!=-1/||/ -F *auid!=4294967295/) &&(/ -C *euid!=uid/||/ -C *uid!=euid/) &&/ -S *execve/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' if ($result1 -match "-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation" -and $result1 -match "-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation" -and $result2 -match "-a always,exit -F arch=b64 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation" -and $result2 -match "-a always,exit -F arch=b32 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.3" Task = "Ensure events that modify the sudo log file are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_4133_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_4133_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-w /var/log/sudo.log -p wa -k sudo_log_file" -and $result2 -match "-w /var/log/sudo.log -p wa -k sudo_log_file") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.4" Task = "Ensure events that modify date and time information are collected" Test = { $script_string1 = @' #!/usr/bin/env bash { awk '/^ *-a *always,exit/ &&/ -F *arch=b[2346]{2}/ &&/ -S/ &&(/adjtimex/ ||/settimeofday/ ||/clock_settime/ ) &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules awk '/^ *-w/ &&/\/etc\/localtime/ &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules } '@ $script_string2 = @' #!/usr/bin/env bash { auditctl -l | awk '/^ *-a *always,exit/ &&/ -F *arch=b[2346]{2}/ &&/ -S/ &&(/adjtimex/ ||/settimeofday/ ||/clock_settime/ ) &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' auditctl -l | awk '/^ *-w/ &&/\/etc\/localtime/ &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' } '@ $result1 = bash -c $script_string1 $result2 = bash -c $script_string2 if ($result1 -match "-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -F key=time-change" -and $result1 -match "-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time-change" -and $result1 -match "-w /etc/localtime -p wa -k time-change" -and $result2 -match "-w /var/log/sudo.log -p wa -k sudo_log_file" -and $result2 -match "-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -F key=time-change" -and $result2 -match "-w /etc/localtime -p wa -k time-change") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.5" Task = "Ensure events that modify the system's network environment are collected" Test = { $script_string1 = @' #!/usr/bin/env bash { awk '/^ *-a *always,exit/ &&/ -F *arch=b(32|64)/ &&/ -S/ &&(/sethostname/ ||/setdomainname/) &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules awk '/^ *-w/ &&(/\/etc\/issue/ ||/\/etc\/issue.net/ ||/\/etc\/hosts/ ||/\/etc\/sysconfig\/network/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules } '@ $script_string2 = @' #!/usr/bin/env bash { auditctl -l | awk '/^ *-a *always,exit/ &&/ -F *arch=b(32|64)/ &&/ -S/ &&(/sethostname/ ||/setdomainname/) &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' auditctl -l | awk '/^ *-w/ &&(/\/etc\/issue/ ||/\/etc\/issue.net/ ||/\/etc\/hosts/ ||/\/etc\/sysconfig\/network/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' } '@ $result1 = bash -c $script_string1 $result2 = bash -c $script_string2 if ($result1 -match "-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale" -and $result1 -match "-a always,exit -F arch=b32 -S sethostname,setdomainname -k system-locale" -and $result1 -match "-w /etc/issue -p wa -k system-locale" -and $result1 -match "-w /etc/issue.net -p wa -k system-locale" -and $result1 -match "-w /etc/hosts -p wa -k system-locale" -and $result1 -match "-w /etc/sysconfig/network -p wa -k system-locale" -and $result1 -match "-w /etc/sysconfig/network-scripts/ -p wa -k system-locale" -and $result2 -match "-a always,exit -F arch=b64 -S sethostname,setdomainname -F key=system-locale" -and $result2 -match "-a always,exit -F arch=b32 -S sethostname,setdomainname -F key=system-locale" -and $result2 -match "-w /etc/issue -p wa -k system-locale" -and $result2 -match "-w /etc/issue.net -p wa -k system-locale" -and $result2 -match "-w /etc/hosts -p wa -k system-locale" -and $result2 -match "-w /etc/sysconfig/network -p wa -k system-locale" -and $result2 -match "-w /etc/sysconfig/network-scripts -p wa -k system-locale") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.6" Task = "Ensure use of privileged commands are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_4136_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_4136_2.sh" $result2 = bash $resultScript2 if ($result1 -match "Warning" -or $result2 -match "Warning") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "4.1.3.7" Task = "Ensure unsuccessful file access attempts are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_4137_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_4137_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -k access" -and $result1 -match "-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -k access" -and $result1 -match "-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -k access" -and $result1 -match "-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -k access" -and $result2 -match "-a always,exit -F arch=b64 -S open,truncate,ftruncate,creat,openat -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access" -and $result2 -match "-a always,exit -F arch=b64 -S open,truncate,ftruncate,creat,openat -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access" -and $result2 -match "-a always,exit -F arch=b32 -S open,truncate,ftruncate,creat,openat -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access" -and $result2 -match "-a always,exit -F arch=b32 -S open,truncate,ftruncate,creat,openat -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.8" Task = "Ensure events that modify user/group information are collected" Test = { $script_string1 = @' #!/usr/bin/env bash { awk '/^ *-w/ &&(/\/etc\/group/ ||/\/etc\/passwd/ ||/\/etc\/gshadow/ ||/\/etc\/shadow/ ||/\/etc\/security\/opasswd/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules } '@ $script_string2 = @' #!/usr/bin/env bash { auditctl -l | awk '/^ *-w/ &&(/\/etc\/group/ ||/\/etc\/passwd/ ||/\/etc\/gshadow/ ||/\/etc\/shadow/ ||/\/etc\/security\/opasswd/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' } '@ $result1 = bash -c $script_string1 $result2 = bash -c $script_string2 if ($result1 -match "-w /etc/group -p wa -k identity" -and $result1 -match "-w /etc/passwd -p wa -k identity" -and $result1 -match "-w /etc/gshadow -p wa -k identity" -and $result1 -match "-w /etc/shadow -p wa -k identity" -and $result1 -match "-w /etc/security/opasswd -p wa -k identity" -and $result2 -match "-w /etc/group -p wa -k identity" -and $result2 -match "-w /etc/passwd -p wa -k identity" -and $result2 -match "-w /etc/gshadow -p wa -k identity" -and $result2 -match "-w /etc/shadow -p wa -k identity" -and $restul2 -match "-w /etc/security/opasswd -p wa -k identity") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.9" Task = "Ensure discretionary access control permission modification events are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_4139_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_4139_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result1 -match "-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result1 -match "-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result1 -match "-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result1 -match "-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result1 -match "-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=-1 -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>=1000 -F auid!=-1 -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=-1 -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>=1000 -F auid!=-1 -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=-1 -F key=perm_mod" -and $result2 -match "-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=-1 -F key=perm_mod") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.10" Task = "Ensure successful file system mounts are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41310_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_41310_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=unset -k mounts" -and $result1 -match "-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=unset -k mounts" -and $result2 -match "-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=-1 -F key=mounts" -and $result2 -match "-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=-1 -F key=mounts") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.11" Task = "Ensure session initiation information is collected" Test = { $script_string1 = @' #!/usr/bin/env bash { awk '/^ *-w/ &&(/\/var\/run\/utmp/ ||/\/var\/log\/wtmp/ ||/\/var\/log\/btmp/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules } '@ $script_string2 = @' #!/usr/bin/env bash { auditctl -l | awk '/^ *-w/ &&(/\/var\/run\/utmp/ ||/\/var\/log\/wtmp/ ||/\/var\/log\/btmp/) &&/ +-p *wa/ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' } '@ $result1 = bash -c $script_string1 $result2 = bash -c $script_string2 if ($result1 -match "-w /var/run/utmp -p wa -k session" -and $result1 -match "-w /var/log/wtmp -p wa -k session" -and $result1 -match "-w /var/log/btmp -p wa -k session" -and $result2 -match "-w /var/run/utmp -p wa -k session" -and $result2 -match "-w /var/log/wtmp -p wa -k session" -and $result2 -match "-w /var/log/btmp -p wa -k session") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.12" Task = "Ensure login and logout events are collected" Test = { $script_string1 = @' #!/usr/bin/env bash { awk '/^ *-w/ \ &&(/\/var\/log\/lastlog/ \ ||/\/var\/run\/faillock/) \ &&/ +-p *wa/ \ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' /etc/audit/rules.d/*.rules } '@ $script_string2 = @' #!/usr/bin/env bash { auditctl -l | awk '/^ *-w/ \ &&(/\/var\/log\/lastlog/ \ ||/\/var\/run\/faillock/) \ &&/ +-p *wa/ \ &&(/ key= *[!-~]* *$/||/ -k *[!-~]* *$/)' } '@ $result1 = bash -c $script_string1 $result2 = bash -c $script_string2 if ($result1 -match "-w /var/log/lastlog -p wa -k logins" -and $result1 -match "-w /var/run/faillock -p wa -k logins" -and $result2 -match "-w /var/log/lastlog -p wa -k logins" -and $result2 -match "-w /var/run/faillock -p wa -k logins") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.13" Task = "Ensure file deletion events by users are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41313_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_41313_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=unset -k delete" -and $result1 -match "-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=unset -k delete" -and $result2 -match "-a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>=1000 -F auid!=-1 -F key=delete" -and $result2 -match "-a always,exit -F arch=b32 -S unlink,rename,unlinkat,renameat -F auid>=1000 -F auid!=-1 -F key=delete") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.14" Task = "Ensure events that modify the system's Mandatory Access Controls are collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41314_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_41314_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-w /etc/selinux -p wa -k MAC-policy" -and $result1 -match "-w /usr/share/selinux -p wa -k MAC-policy" -and $result2 -match "-w /etc/selinux -p wa -k MAC-policy" -and $result2 -match "-w /usr/share/selinux -p wa -k MAC-policy") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.15" Task = "Ensure successful and unsuccessful attempts to use the chcon command are recorded" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41315_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_41315_2.sh" $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng" -and $result2 -match "-a always,exit -S all -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=-1 -F key=perm_chng") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.16" Task = "Ensure successful and unsuccessful attempts to use the setfacl command are recorded" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41316_1.sh" $resultScript2 = $scriptPath + "CIS100_RHEL9_41316_2.sh" $result1 = bash $resultScript1 $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng" -and $result2 -match "-a always,exit -S all -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=-1 -F key=perm_chng") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.17" Task = "Ensure successful and unsuccessful attempts to use the chacl command are recorded" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41317_1.sh" $resultScript2 = $scriptPath + "CIS100_RHEL9_41317_2.sh" $result1 = bash $resultScript1 $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng" -and $result2 -match "-a always,exit -S all -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=-1 -F key=perm_chng") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.18" Task = "Ensure successful and unsuccessful attempts to use the usermod command are recorded" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41318_1.sh" $resultScript2 = $scriptPath + "CIS100_RHEL9_41318_2.sh" $result1 = bash $resultScript1 $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset -k usermod" -and $result2 -match "-a always,exit -S all -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=-1 -F key=usermod") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.19" Task = "Ensure kernel module loading unloading and modification is collected" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_41319_1.sh" $resultScript2 = $scriptPath + "CIS100_RHEL9_41319_2.sh" $result1 = bash $resultScript1 $result2 = bash $resultScript2 if ($result1 -match "-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>=1000 -F auid!=unset -k kernel_modules" -and $result1 -match "-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset -k kernel_modules" -and $result2 -match "-a always,exit -F arch=b64 -S create_module,init_module,delete_module,query_module,finit_module -F auid>=1000 -F auid!=-1 -F key=kernel_modules" -and $result2 -match "-a always,exit -S all -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=-1 -F key=kernel_modules" -and $result3 -match "OK") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.20" Task = "Ensure the audit configuration is immutable" Test = { $result1 = grep -Ph -- '^\h*-e\h+2\b' /etc/audit/rules.d/*.rules | tail -1 if ($result1 -match "-e 2") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.3.21" Task = "Ensure the running and on disk configuration is the same" Test = { $result1 = augenrules --check if ($result1 -match "/usr/sbin/augenrules: No change") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.1" Task = "Ensure audit log files are mode 0640 or less permissive" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_4141.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.2" Task = "Ensure only authorized users own audit log files" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_3412.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.3" Task = "Ensure only authorized groups are assigned ownership of audit log files" Test = { $script_string1 = @' #!/usr/bin/env bash { stat -c "%n %G" "$(dirname $(awk -F"=" '/^\s*log_file\s*=\s*/ {print $2}' /etc/audit/auditd.conf | xargs))"/* | grep -Pv '^\h*\H+\h+(adm|root)\b' } '@ $result1 = bash -c $script_string1 $result2 = grep -Piw -- '^\h*log_group\h*=\h*(adm|root)\b' /etc/audit/auditd.conf if (($result1 -match "log_group = adm" -or $result1 -match "log_group = root") -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.4" Task = "Ensure the audit log directory is 0750 or more restrictive" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_4144.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.5" Task = "Ensure audit configuration files are 640 or more restrictive" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_4145.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.6" Task = "Ensure audit configuration files are owned by root" Test = { $result1_string = @' #!/usr/bin/env bash { find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -user root } '@ $result1 = bash -c $result1_string if ($result1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.7" Task = "Ensure audit configuration files belong to group root" Test = { $result1_string = @' #!/usr/bin/env bash { find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -group root } '@ $result1 = bash -c $result1_string if ($result1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.8" Task = "Ensure audit tools are 755 or more restrictive" Test = { $result1 = stat -c "%n %a" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/augenrules | grep -Pv -- '^\h*\H+\h+([0-7][0,1,4,5][0,1,4,5])\h*$' if ($result1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.9" Task = "Ensure audit tools are owned by root" Test = { $result1 = stat -c "%n %U" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/augenrules | grep -Pv -- '^\h*\H+\h+root\h*$' if ($result1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.1.4.10" Task = "Ensure audit tools belong to group root" Test = { $result1 = stat -c "%n %a %U %G" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/augenrules | grep -Pv -- '^\h*\H+\h+([0-7][0,1,4,5][0,1,4,5])\h+root\h+root\h*$' if ($result1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.1.1" Task = "Ensure rsyslog is installed" Test = { $result1 = rpm -q rsyslog if ($result1 -match "rsyslog-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.1.2" Task = "Ensure rsyslog service is enabled" Test = { $result1 = systemctl is-enabled rsyslog if ($result1 -match "enabled") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.1.3" Task = "Ensure journald is configured to send logs to rsyslog" Test = { $result1 = grep ^\s*ForwardToSyslog /etc/systemd/journald.conf if ($result1 -match "ForwardToSyslog=yes") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.1.4" Task = "Ensure journald is configured to send logs to rsyslog" Test = { $result1 = grep -Ps '^\h*\$FileCreateMode\h+0[0,2,4,6][0,2,4]0\b' /etc/rsyslog.conf /etc/rsyslog.d/*.conf if ($result1 -match "FileCreateMode 0640") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.1.5" Task = "Ensure logging is configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.1.6" Task = "Ensure rsyslog is configured to send logs to a remote log host" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.1.7" Task = "Ensure journald is configured to send logs to rsyslog" Test = { $result1 = grep -Ps -- '^\h*module\(load="imtcp"\)' /etc/rsyslog.conf /etc/rsyslog.d/*.conf $result2 = grep -Ps -- '^\h*input\(type="imtcp" port="514"\)' /etc/rsyslog.conf /etc/rsyslog.d/*.conf if ($result1 -eq $null -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.1.1" Task = "Ensure journald is configured to send logs to rsyslog" Test = { $result1 = rpm -q systemd-journal-remote if ($result1 -eq "systemd-journal-remote-") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.1.2" Task = "Ensure systemd-journal-remote is configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.2.1.3" Task = "Ensure systemd-journal-remote is enabled" Test = { $result1 = systemctl is-enabled systemd-journal-upload.service if ($result1 -match "enabled") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.1.4" Task = "Ensure journald is not configured to receive logs from a remote client" Test = { $result1 = systemctl is-enabled systemd-journal-remote.socket if ($result1 -match "masked") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.2" Task = "Ensure journald service is enabled" Test = { $result1 = systemctl is-enabled systemd-journald.service if ($result1 -match "static") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.3" Task = "Ensure journald is configured to compress large log files" Test = { $result1 = grep ^\s*Compress /etc/systemd/journald.conf if ($result1 -match "Compress=yes") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.4" Task = "Ensure journald is configured to write logfiles to persistent disk" Test = { $result1 = grep ^\s*Storage /etc/systemd/journald.conf if ($result1 -match "Storage=persistent") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.2.2.5" Task = "Ensure journald is not configured to send logs to rsyslog" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.2.6" Task = "Ensure journald log rotation is configured per site policy" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.2.7" Task = "Ensure journald default file permissions configured" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "4.2.3" Task = "Ensure all logfiles have appropriate permissions and ownership" Test = { $script_string = @' #!/usr/bin/env bash { echo -e "\n- Start check - logfiles have appropriate permissions and ownership" output="" UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs) find /var/log -type f | (while read -r fname; do bname="$(basename "$fname")" fugname="$(stat -Lc "%U %G" "$fname")" funame="$(awk '{print $1}' <<< "$fugname")" fugroup="$(awk '{print $2}' <<< "$fugname")" fuid="$(stat -Lc "%u" "$fname")" fmode="$(stat -Lc "%a" "$fname")" case "$bname" in lastlog | lastlog.* | wtmp | wtmp.* | wtmp-* | btmp | btmp.* | btmp-*) if ! grep -Pq -- '^\h*[0,2,4,6][0,2,4,6][0,4]\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if ! grep -Pq -- '^\h*root\h+(utmp|root)\h*$' <<< "$fugname"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi ;; secure | auth.log | syslog | messages) if ! grep -Pq -- '^\h*[0,2,4,6][0,4]0\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if ! grep -Pq -- '^\h*(syslog|root)\h+(adm|root)\h*$' <<< "$fugname"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi ;; SSSD | sssd) if ! grep -Pq -- '^\h*[0,2,4,6][0,2,4,6]0\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if ! grep -Piq -- '^\h*(SSSD|root)\h+(SSSD|root)\h*$' <<< "$fugname"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi ;; gdm | gdm3) if ! grep -Pq -- '^\h*[0,2,4,6][0,2,4,6]0\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if ! grep -Pq -- '^\h*(root)\h+(gdm3?|root)\h*$' <<< "$fugname"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi ;; *.journal | *.journal~) if ! grep -Pq -- '^\h*[0,2,4,6][0,4]0\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if ! grep -Pq -- '^\h*(root)\h+(systemd-journal|root)\h*$' <<< "$fugname"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi ;; *) if ! grep -Pq -- '^\h*[0,2,4,6][0,4]0\h*$' <<< "$fmode"; then output="$output\n- File: \"$fname\" mode: \"$fmode\"\n" fi if [ "$fuid" -ge "$UID_MIN" ] || ! grep -Pq -- '(adm|root|'"$(id -gn "$funame")"')' <<< "$fugroup"; then if [ -n "$(awk -v grp="$fugroup" -F: '$1==grp {print $4}' /etc/group)" ] || ! grep -Pq '(syslog|root)' <<< "$funame"; then output="$output\n- File: \"$fname\" ownership: \"$fugname\"\n" fi fi ;; esac done # If all files passed, then we pass if [ -z "$output" ]; then echo -e "\n- Audit Results:\n PASS\n- All files in \"/var/log/\" have appropriate permissions and ownership\n" else # print the reason why we are failing echo -e "\n- Audit Results:\n FAIL\n$output" fi echo -e "- End check - logfiles have appropriate permissions and ownership\n" ) } '@ $script = bash -c $script_string if ($script -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "4.3" Task = "Ensure logrotate is configured" Test = { return $retNonCompliantManualReviewRequired } } ### Chapter 5 - Access, Authentication and Authorization [AuditTest] @{ Id = "5.1.1" Task = "Ensure cron daemon is enabled" Test = { $result1 = systemctl is-enabled crond if ($result1 -match "enabled") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.2" Task = "Ensure permissions on /etc/crontab are configured" Test = { $result1 = stat -c "%a" /etc/crontab if ($result1 -eq 600 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.3" Task = "Ensure permissions on /etc/cron.hourly are configured" Test = { $result1 = stat -c "%a" /etc/cron.hourly if ($result1 -eq 700 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.4" Task = "Ensure permissions on /etc/cron.daily are configured" Test = { $result1 = stat -c "%a" /etc/cron.daily if ($result1 -eq 700 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.5" Task = "Ensure permissions on /etc/cron.weekly are configured" Test = { $result1 = stat -c "%a" /etc/cron.weekly if ($result1 -eq 700 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.6" Task = "Ensure permissions on /etc/cron.monthly are configured" Test = { $result1 = stat -c "%a" /etc/cron.monthly if ($result1 -eq 700 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.7" Task = "Ensure permissions on /etc/cron.d are configured" Test = { $result1 = stat -c "%a" /etc/cron.d if ($result1 -eq 700 ) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.8" Task = "Ensure cron is restricted to authorized users" Test = { $script_string = @' #!/usr/bin/env bash { if rpm -q cronie >/dev/null; then [ -e /etc/cron.deny ] && echo "Fail: cron.deny exists" if [ ! -e /etc/cron.allow ]; then echo "Fail: cron.allow doesn't exist" else ! stat -Lc "%a" /etc/cron.allow | grep -Eq "[0,2,4,6]00" && echo "Fail: cron.allow mode too permissive" ! stat -Lc "%u:%g" /etc/cron.allow | grep -Eq "^0:0$" && echo "Fail: cron.allow owner and/or group not root" fi if [ ! -e /etc/cron.deny ] && [ -e /etc/cron.allow ] && stat -Lc "%a" /etc/cron.allow | grep -Eq "[0,2,4,6]00" \ && stat -Lc "%u:%g" /etc/cron.allow | grep -Eq "^0:0$"; then echo "Pass" fi else echo "PASS: cron is not installed on the system" fi } '@ $script = bash -c $script_string if ($script -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.1.9" Task = "Ensure at is restricted to authorized users" Test = { $script_string = @' #!/usr/bin/env bash { if rpm -q at >/dev/null; then [ -e /etc/at.deny ] && echo "Fail: at.deny exists" if [ ! -e /etc/at.allow ]; then echo "Fail: at.allow doesn't exist" else ! stat -Lc "%a" /etc/at.allow | grep -Eq "[0,2,4,6]00" && echo "Fail: at.allow mode too permissive" ! stat -Lc "%u:%g" /etc/at.allow | grep -Eq "^0:0$" && echo "Fail: at.allow owner and/or group not root" fi if [ ! -e /etc/at.deny ] && [ -e /etc/at.allow ] && stat -Lc "%a" /etc/at.allow | grep -Eq "[0,2,4,6]00" && stat -Lc "%u:%g" /etc/at.allow | grep -Eq "^0:0$"; then echo "PASS" fi else echo "PASS: at is not installed on the system" fi } '@ $script = bash -c $script_string if ($script -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.1" Task = "Ensure permissions on /etc/ssh/sshd_config are configured" Test = { $result1 = stat -Lc "%n %a %u/%U %g/%G" /etc/ssh/sshd_config if ($result1 -match "/etc/ssh/sshd_config 600 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.2" Task = "Ensure permissions on SSH private host key files are configured" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_522.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.3" Task = "Ensure permissions on SSH public host key files are configured" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_523.sh" $result = bash $resultScript if ($result -match "PASS") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.4" Task = "Ensure SSH access is limited" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -Pi '^\h*(allow|deny)(users|groups)\h+\H+(\h+.*)?$' $test2 = grep -Pi '^\h*(allow|deny)(users|groups)\h+\H+(\h+.*)?$' /etc/ssh/sshd_config if ($test1 -match "allowusers " -or $test1 -match "allowgroups " -or $test1 -match "denyusers " -or $test1 -match "denygroups " -or $test2 -match "allowusers " -or $test2 -match "allowgroups " -or $test2 -match "denyusers " -or $test2 -match "denygroups ") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.5" Task = "Ensure SSH LogLevel is appropriate" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -Pi '^\h*(allow|deny)(users|groups)\h+\H+(\h+.*)?$' $test2 = grep -Pi '^\h*(allow|deny)(users|groups)\h+\H+(\h+.*)?$' /etc/ssh/sshd_config if (($test1 -match "allowusers " -or $test1 -match "allowgroups " -or $test1 -match "denyusers " -or $test1 -match "denygroups ") -and ($test2 -match "allowusers " -or $test2 -match "allowgroups " -or $test2 -match "denyusers " -or $test2 -match "denygroups ")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.6" Task = "Ensure SSH PAM is enabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -i usepam $test2 = grep -Pi '^\h*(allow|deny)(users|groups)\h+\H+(\h+.*)?$' /etc/ssh/sshd_config if ($test1 -match "usepam yes" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.7" Task = "Ensure SSH root login is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep permitrootlogin $test2 = grep -Ei '^\s*PermitRootLogin\s+yes' /etc/ssh/sshd_config if ($test1 -match "permitrootlogin no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.8" Task = "Ensure SSH HostbasedAuthentication is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep hostbasedauthentication $test2 = grep -Ei '^\s*HostbasedAuthentication\s+yes' /etc/ssh/sshd_config if ($test1 -match "permitrootlogin no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.9" Task = "Ensure SSH PermitEmptyPasswords is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep permitemptypasswords $test2 = grep -Ei '^\s*PermitEmptyPasswords\s+yes' /etc/ssh/sshd_config if ($test1 -match "permitemptypasswords no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.10" Task = "Ensure SSH PermitUserEnvironment is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep permituserenvironment $test2 = grep -Ei '^\s*PermitUserEnvironment\s+yes' /etc/ssh/sshd_config if ($test1 -match "permituserenvironment no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.11" Task = "Ensure SSH IgnoreRhosts is enabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep ignorerhosts $test2 = grep -Ei '^\s*ignorerhosts\s+no\b' /etc/ssh/sshd_config if ($test1 -match "ignorerhosts yes" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.12" Task = "Ensure SSH X11 forwarding is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -i x11forwarding $test2 = grep -Ei '^\s*x11forwarding\s+yes' /etc/ssh/sshd_config if ($test1 -match "x11forwarding no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.13" Task = "Ensure SSH AllowTcpForwarding is disabled" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -i allowtcpforwarding $test2 = grep -Ei '^\s*AllowTcpForwarding\s+yes' /etc/ssh/sshd_config if ($test1 -match "allowtcpforwarding no" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.14" Task = "Ensure system-wide crypto policy is not over-ridden" Test = { $test = grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.15" Task = "Ensure SSH warning banner is configured" Test = { $test = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep banner if ($test -match "banner /etc/issue.net") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.16" Task = "Ensure SSH MaxAuthTries is set to 4 or less" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep maxauthtries $test2 = grep -Ei '^\s*maxauthtries\s+([5-9]|[1-9][0-9]+)' /etc/ssh/sshd_config if ($test1 -match "maxauthtries 4" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.17" Task = "Ensure SSH MaxStartups is configured" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -i maxstartups $test2 = grep -Ei '^\s*maxstartups\s+(((1[1-9]|[1-9][0-9][0-9]+):([0-9]+):([0-9]+))|(([0-9]+):(3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):([0-9]+))|(([0-9]+):([0-9]+):(6[1-9]|[7-9][0-9]|[1-9][0-9][0-9]+)))' /etc/ssh/sshd_config if ($test1 -match "maxstartups 10:30:60" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.18" Task = "Ensure SSH MaxSessions is set to 10 or less" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep -i maxsessions $test2 = grep -Ei '^\s*MaxSessions\s+(1[1-9]|[2-9][0-9]|[1-9][0-9][0-9]+)' /etc/ssh/sshd_config if ($test1 -match "maxsessions 10" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.19" Task = "Ensure SSH LoginGraceTime is set to one minute or less" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep logingracetime $test2 = grep -Ei '^\s*LoginGraceTime\s+(0|6[1-9]|[7-9][0-9]|[1-9][0-9][0-9]+|[^1]m)' /etc/ssh/sshd_config if ($test1 -match "logingracetime 60" -and $test2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.2.20" Task = "Ensure SSH Idle Timeout Interval is configured" Test = { $test1 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep clientaliveinterval | cut -d ' ' -f 2 $test2 = sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | awk '{print $1}')" | grep clientalivecountmax | cut -d ' ' -f 2 if ($test1 -gt 0 -and $test2 -gt 0) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.1" Task = "Ensure SUDO is installed" Test = { $test = dnf list sudo | grep sudo.x86_64 if ($test -match "sudo") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.2" Task = "Ensure sudo commands use pty" Test = { $test = grep -rPi '^\h*Defaults\h+([^#\n\r]+,)?use_pty(,\h*\h+\h*)*\h*(#.*)?$' /etc/sudoers* if ($test -match "/etc/sudoers:Defaults use_pty") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.3" Task = "Ensure sudo log file exists" Test = { $test = grep -Ei '^\s*Defaults\s+logfile=\S+' /etc/sudoers /etc/sudoers.d/* if ($test -match "/etc/sudoers:Defaults use_pty") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.4" Task = "Ensure users must provide password for escalation" Test = { $test = grep -r "^[^#].*NOPASSWD" /etc/sudoers* if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.5" Task = "Ensure re-authentication for privilege escalation is not disabled globally" Test = { $test = grep -r "^[^#].*\!authenticate" /etc/sudoers* if ($test -match "!authenticate") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "5.3.6" Task = "Ensure sudo authentication timeout is configured correctly" Test = { $test = grep -roP "timestamp_timeout=\K[0-9]*" /etc/sudoers* | cut -d ' ' -f 2 if ($test -le 15) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.3.7" Task = "Ensure access to the su command is restricted" Test = { $test1 = grep -Pi '^\h*auth\h+(?:required|requisite)\h+pam_wheel\.so\h+(?:[^#\n\r]+\h+)?((?!\2)(use_uid\b|group=\H+\b))\h+(?:[^#\n\r]+\h+)?((?!\1)(use_uid\b|group=\H+\b))(\h+.*)?$' /etc/pam.d/su if ($test1 -match "auth required pam_wheel.so use_uid group=") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.4.1" Task = "Ensure custom authselect profile is used" Test = { $test1 = authselect list | grep '^-\s*custom' if ($test1 -eq $null) { return $retNonCompliant } else { return $retCompliant } } } # 5.4.2 ist leider schlecht beschrieben, die Pruefung ist mit ihren Parametern bestenfalls mangelhaft [AuditTest] @{ Id = "5.4.2" Task = "Ensure authselect includes with-faillock" Test = { $test1 = grep pam_faillock.so /etc/pam.d/password-auth /etc/pam.d/system-auth if ($test1 -match "/etc/authselect/password-auth:auth") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.5.1" Task = "Ensure password creation requirements are configured" Test = { $test1 = grep ^minlen /etc/security/pwquality.conf | cut -d '=' -f 2 if ($test1 -ge 14) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.5.2" Task = "Ensure lockout for failed password attempts is configured" Test = { $test1 = grep -E '^\s*deny\s*=\s*[1-5]\b' /etc/security/faillock.conf | cut -d '=' -f 2 $test2 = grep -E '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b' /etc/security/faillock.conf | cut -d '=' -f 2 if ($test1 -le 5 -and ($test2 -eq 0 -or $test2 -ge 900)) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.5.3" Task = "Ensure password reuse is limited" Test = { $test1 = grep -P '^\h*password\h+(requisite|sufficient)\h+(pam_pwhistory\.so|pam_unix\.so)\h+([^#\n\r]+\h+)?remember=([5-9]|[1-9][0-9]+)\h*(\h+.*)?$' /etc/pam.d/system-auth if ($test1 -match "remember=5") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.5.4" Task = "Ensure password hashing algorithm is SHA-512 or yescrypt" Test = { $test1 = grep -Ei '^\s*crypt_style\s*=\s*(sha512|yescrypt)\b' /etc/libuser.conf $test2 = grep -Ei '^\s*ENCRYPT_METHOD\s+(SHA512|yescrypt)\b' /etc/login.defs if (($test2 -match "ENCRYPT_METHOD SHA512" -or $test2 -match "ENCRYPT_METHOD YESCRYPT") -and ($test1 -match "crypt_style = sha512" -or $test1 -match "crypt_style = yescrypt")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.1.1" Task = "Ensure password expiration is 365 days or less" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_5611_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_5611_2.sh" $result2 = bash $resultScript2 if ($result1 -le 365 -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.1.2" Task = "Ensure minimum days between password changes is configured" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_5612_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_5612_2.sh" $result2 = bash $resultScript2 if ($result1 -ge 1 -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.1.3" Task = "Ensure password expiration warning days is 7 or more" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_5613_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_5613_2.sh" $result2 = bash $resultScript2 if ($result1 -match "PASS_WARN_AGE\s*7" -and !($result2 -match "FAIL")) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.1.4" Task = "Ensure inactive password lock is 30 days or less" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_5614_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_5614_2.sh" $result2 = bash $resultScript2 if ($result1 -ge 2 -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.1.5" Task = "Ensure all users last password change date is in the past" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_5615.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.2" Task = "Ensure system accounts are secured" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_562_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_562_2.sh" $result2 = bash $resultScript2 if ($result1 -eq $null -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.3" Task = "Ensure default user shell timeout is 900 seconds or less" Test = { $script_string = @' #!/usr/bin/env bash { output1="" output2="" [ -f /etc/bashrc ] && BRC="/etc/bashrc" for f in "$BRC" /etc/profile /etc/profile.d/*.sh ; do grep -Pq '^\s*([^#]+\s+)?TMOUT=(900|[1-8][0-9][0-9]|[1-9][0-9]|[1-9])\b' "$f" && grep -Pq '^\s*([^#]+;\s*)?readonly\s+TMOUT(\s+|\s*;|\s*$|=(900|[1-8][0-9][0-9]|[1-9][0-9]|[1-9]))\b' "$f" && grep -Pq '^\s*([^#]+;\s*)?export\s+TMOUT(\s+|\s*;|\s*$|=(900|[1-8][0-9][0-9]|[1-9][0-9]|[1-9]))\b' "$f" && output1="$f" done grep -Pq '^\s*([^#]+\s+)?TMOUT=(9[0-9][1-9]|9[1-9][0-9]|0+|[1-9]\d{3,})\b' /etc/profile /etc/profile.d/*.sh "$BRC" && output2=$(grep -Ps '^\s*([^#]+\s+)?TMOUT=(9[0-9][1-9]|9[1-9][0-9]|0+|[1-9]\d{3,})\b' /etc/profile /etc/profile.d/*.sh $BRC) if [ -n "$output1" ] && [ -z "$output2" ]; then echo -e "\nPASSED\n\nTMOUT is configured in: \"$output1\"\n" else [ -z "$output1" ] && echo -e "\nFAILED\n\nTMOUT is not configured\n" [ -n "$output2" ] && echo -e "\nFAILED\n\nTMOUT is incorrectly configured in: \"$output2\"\n" fi } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.4" Task = "Ensure default group for the root account is GID 0" Test = { $test1 = grep "^root:" /etc/passwd | cut -f4 -d ':' if ($test1 -eq 0) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.5" Task = "Ensure default user shell timeout is 900 seconds or less" Test = { $resultScript1 = $scriptPath + "CIS100_RHEL9_565_1.sh" $result1 = bash $resultScript1 $resultScript2 = $scriptPath + "CIS100_RHEL9_565_2.sh" $result2 = bash $resultScript2 if ($result1 -match "umask is set" -and $result2 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "5.6.6" Task = "Ensure root password is set" Test = { $test1 = passwd -S root if ($test1 -match "Password set") { return $retCompliant } else { return $retNonCompliant } } } ### Chapter 6 - System Maintenance [AuditTest] @{ Id = "6.1.1" Task = "Ensure permissions on /etc/passwd are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/passwd if ($test1 -match "644 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.2" Task = "Ensure permissions on /etc/passwd are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/passwd- if ($test1 -match "644 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.3" Task = "Ensure permissions on /etc/group are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/group if ($test1 -match "644 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.4" Task = "Ensure permissions on /etc/group- are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/group- if ($test1 -match "644 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.5" Task = "Ensure permissions on /etc/shadow are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/shadow if ($test1 -match "0 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.6" Task = "Ensure permissions on /etc/shadow- are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/shadow- if ($test1 -match "0 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.7" Task = "Ensure permissions on /etc/gshadow are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/gshadow if ($test1 -match "0 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.7" Task = "Ensure permissions on /etc/gshadow are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/gshadow if ($test1 -match "0 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.8" Task = "Ensure permissions on /etc/gshadow- are configured" Test = { $test1 = stat -Lc "%n %a %u/%U %g/%G" /etc/gshadow- if ($test1 -match "0 0/root 0/root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.9" Task = "Ensure no world writable files exist" Test = { $test1 = df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -type f -perm -0002 if ($test1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.10" Task = "Ensure no unowned files or directories exist" Test = { $test1 = df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -nouser if ($test1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.11" Task = "Ensure no ungrouped files or directories exist" Test = { $test1 = df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -nogroup if ($test1 -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.12" Task = "Ensure sticky bit is set on all world-writable directories" Test = { $test_string = "df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -type d \( -perm -0002 -a ! -perm -1000 \) 2>/dev/null" $test = bash -c $test_string if ($test -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.1.13" Task = "Audit SUID executables" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "6.1.14" Task = "Audit SGID executables" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "6.1.15" Task = "Audit system file permissions" Test = { return $retNonCompliantManualReviewRequired } } [AuditTest] @{ Id = "6.2.1" Task = "Ensure accounts in /etc/passwd use shadowed passwords" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_621.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.2" Task = "Ensure /etc/shadow password fields are not empty" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_622.sh" $result = bash $resultScript if ($result -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.3" Task = "Ensure all groups in /etc/passwd exist in /etc/group" Test = { $script_string = @' #!/usr/bin/env bash { for i in $(cut -s -d: -f4 /etc/passwd | sort -u ); do grep -q -P "^.*?:[^:]*:$i:" /etc/group if [ $? -ne 0 ]; then echo "Group $i is referenced by /etc/passwd but does not exist in /etc/group" fi done } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.4" Task = "Ensure no duplicate UIDs exist" Test = { $script_string = @' #!/usr/bin/env bash { cut -f3 -d":" /etc/passwd | sort -n | uniq -c | while read x ; do [ -z "$x" ] && break set - $x if [ $1 -gt 1 ]; then users=$(awk -F: '($3 == n) { print $1 }' n=$2 /etc/passwd | xargs) echo "Duplicate UID ($2): $users" fi done } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.5" Task = "Ensure no duplicate GIDs exist" Test = { $script_string = @' #!/usr/bin/env bash { cut -d: -f3 /etc/group | sort | uniq -d | while read x ; do echo "Duplicate GID ($x) in /etc/group" done } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.6" Task = "Ensure no duplicate user names exist" Test = { $script_string = @' #!/usr/bin/env bash { cut -d: -f1 /etc/passwd | sort | uniq -d | while read -r x; do echo "Duplicate login name $x in /etc/passwd" done } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.7" Task = "Ensure no duplicate group names exist" Test = { $script_string = @' #!/usr/bin/env bash { cut -d: -f1 /etc/group | sort | uniq -d | while read -r x; do echo "Duplicate group name $x in /etc/group" done } '@ $script = bash -c $script_string if ($script -eq $null) { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.8" Task = "Ensure root PATH Integrity" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_628.sh" $result = bash $resultScript if ($result -match "is not a directory") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.9" Task = "Ensure root is the only UID 0 account" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_629.sh" $result = bash $resultScript if ($result -eq "root") { return $retCompliant } else { return $retNonCompliant } } } [AuditTest] @{ Id = "6.2.10" Task = "Ensure local interactive user home directories exist" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6210.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.11" Task = "Ensure local interactive users own their home directories" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6210.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.12" Task = "Ensure local interactive user home directories are mode 750 or more restrictive" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6212.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.13" Task = "Ensure no local interactive user has .netrc files" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6213.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.14" Task = "Ensure no local interactive user has .forward files" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6214.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.15" Task = "Ensure no local interactive user has .rhosts files" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6215.sh" $result = bash $resultScript if ($result -match "FAILED") { return $retNonCompliant } else { return $retCompliant } } } [AuditTest] @{ Id = "6.2.16" Task = "Ensure local interactive user dot files are not group or world writable" Test = { $resultScript = $scriptPath + "CIS100_RHEL9_6216.sh" $result = bash $resultScript if ($result -match "Failed") { return $retNonCompliant } else { return $retCompliant } } }