#!/usr/bin/env bash set -o pipefail set -o nounset set -o errexit tmpfs_and_mount() { FOLDER_PATH=$1 mkdir -p ${FOLDER_PATH} echo "tmpfs ${FOLDER_PATH} tmpfs mode=1777,strictatime,noexec,nodev,nosuid 0 0" >> /etc/fstab mount -a } unload_module() { local fsname=$1 rmmod "${fsname}" || true mkdir -p /etc/modprobe.d/ echo "install ${fsname} /bin/true" > "/etc/modprobe.d/${fsname}.conf" } systemd_disable() { local service_name=$1 if systemctl is-enabled $service_name; then systemctl disable $service_name fi } yum_remove() { local package_name=$1 if rpm -q $package_name; then yum remove -y $package_name fi } sysctl_entry() { local entry=$1 echo "$entry" >> /etc/sysctl.d/cis.conf } set_conf_value() { local key=$1 local value=$2 local file=$3 sed -i "s/^\(${key}\s*=\s*\).*$/\1${value}/" $file } echo "1.1.1.1 - ensure mounting of cramfs filesystems is disabled" unload_module cramfs echo "1.1.1.2 - ensure mounting of squashfs filesystems is disabled" unload_module squashfs echo "1.1.1.3 - ensure mounting of udf filesystems is disabled" unload_module udf echo "1.1.2 - 1.1.5 - ensure /tmp is configured noexec,nodev,nosuid options set on /tmp partition" systemctl unmask tmp.mount && systemctl enable tmp.mount cat > /etc/systemd/system/local-fs.target.wants/tmp.mount <> /etc/fstab mount -a echo "1.1.10 - ensure separate partition exists for /var" echo "1.1.11 - 1.1.14 - ensure separate partition exists for /var/tmp noexec,nodev,nosuid option set" tmpfs_and_mount /var/tmp echo "1.1.15 - ensure separate partition exists for /var/log" echo "1.1.16 - ensure separate partition exists for /var/log/audit" echo "1.1.17 - 1.1.18 - ensure separate partition exists for /home nodev option set" echo "1.1.19 - 1.1.21 - ensure removable media partitions include noexec,nodev,nosuid option" echo "1.1.22 - ensure sticky bit is set on all world-writable directories" echo "1.1.23 - disable automounting" yum_remove autofs echo "1.1.24 - disable usb storage" echo "install usb-storage /bin/true" > /etc/modprobe.d/usb_storage.conf echo "1.2.1 - ensure GPG keys are configured" rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' echo "1.2.2 - ensure package manager repositories are configured" yum repolist echo "1.2.3 - ensure gpgcheck is globally activated" grep ^gpgcheck /etc/yum.conf grep ^gpgcheck /etc/yum.repos.d/* echo "1.3.1 - ensure AIDE is installed" yum install -y aide aide --init mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz echo "1.3.2 - ensure filesystem integrity is regularly checked" echo "0 5 * * * root /usr/sbin/aide --check" > /etc/cron.d/aide echo "1.4.1 - ensure permissions on bootloader config are configured" chown root:root /boot/grub2/grub.cfg chmod og-rwx /boot/grub2/grub.cfg echo "1.4.2 - ensure authentication required for single user mode" cat > /usr/lib/systemd/system/rescue.service < /usr/lib/systemd/system/emergency.service < /etc/security/limits.d/cis.conf sysctl_entry "fs.suid_dumpable = 0" echo "1.5.2 - ensure XD/NX support is enabled" echo "1.5.3 - ensure address space layout randomization (ASLR) is enabled" sysctl_entry "kernel.randomize_va_space = 2" echo "1.5.4 - ensure prelink is disabled" yum_remove prelink echo "1.6.1.4 - ensure the SELinux mode is enforcing or permissive" sed -i 's/SELINUX=disabled/SELINUX=enforcing/g' /etc/selinux/config echo "1.7.1.1 - ensure message of the day is configured properly" rm -f /etc/cron.d/update-motd cat > /etc/update-motd.d/30-banner <<"OUTEREOF" #!/bin/sh cat <<"EOF" You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions: -The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations. -At any time, the USG may inspect and seize data stored on this IS. -Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose. -This IS includes security measures (e.g., authentication and access controls) to protect USG interests--not for your personal benefit or privacy. -Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details. EOF OUTEREOF echo "1.7.1.2 - ensure local login warning banner is configured properly" cat > /etc/issue < /etc/issue.net <> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b64 -S clock_settime -k time-change" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S clock_settime -k time-change" >> /etc/audit/rules.d/cis.rules echo "-w /etc/localtime -p wa -k time-change" >> /etc/audit/rules.d/cis.rules echo "4.1.5 - ensure events that modify user/group information are collected" echo "-w /etc/group -p wa -k identity" >> /etc/audit/rules.d/cis.rules echo "-w /etc/passwd -p wa -k identity" >> /etc/audit/rules.d/cis.rules echo "-w /etc/gshadow -p wa -k identity" >> /etc/audit/rules.d/cis.rules echo "-w /etc/shadow -p wa -k identity" >> /etc/audit/rules.d/cis.rules echo "-w /etc/security/opasswd -p wa -k identity" >> /etc/audit/rules.d/cis.rules echo "4.1.6 - ensure events that modify the system's network environment are collected" echo "-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-w /etc/issue -p wa -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-w /etc/issue.net -p wa -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-w /etc/hosts -p wa -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-w /etc/sysconfig/network -p wa -k system-locale" >> /etc/audit/rules.d/cis.rules echo "-w /etc/sysconfig/network-scripts/ -p wa -k system-locale" >> /etc/audit/rules.d/cis.rules echo "4.1.6 - ensure events that modify the system's network environment are collected" echo "-w /etc/selinux/ -p wa -k MAC-policy" >> /etc/audit/rules.d/cis.rules echo "-w /usr/share/selinux/ -p wa -k MAC-policy" >> /etc/audit/rules.d/cis.rules echo "4.1.8 - ensure login and logout events are collected" echo "-w /var/log/lastlog -p wa -k logins" >> /etc/audit/rules.d/cis.rules echo "-w /var/run/faillock/ -p wa -k logins" >> /etc/audit/rules.d/cis.rules echo "4.1.9 - ensure session initiation information is collected" echo "-w /var/run/utmp -p wa -k session" >> /etc/audit/rules.d/cis.rules echo "-w /var/log/wtmp -p wa -k logins" >> /etc/audit/rules.d/cis.rules echo "-w /var/log/btmp -p wa -k logins" >> /etc/audit/rules.d/cis.rules echo "4.1.10 - ensure discretionary access control permission modification events are collected" echo "-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod" >> /etc/audit/rules.d/cis.rules echo "4.1.11 - ensure unsuccessful unauthorized file access attempts are collected" echo "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" >> /etc/audit/rules.d/cis.rules echo "4.1.12 - ensure use of privileged commands is collected" find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print \ "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=4294967295 \ -k privileged" }' >> /etc/audit/rules.d/cis.rules echo "4.1.13 - ensure successful file system mounts are collected" echo "-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts" >> /etc/audit/rules.d/cis.rules echo "4.1.14 - ensure file deletion events by users are collected" echo "-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete" >> /etc/audit/rules.d/cis.rules echo "4.1.15 - ensure changes to system administration scope (sudoers) is collected" echo "-w /etc/sudoers -p wa -k scope" >> /etc/audit/rules.d/cis.rules echo "-w /etc/sudoers.d/ -p wa -k scope" >> /etc/audit/rules.d/cis.rules echo "4.1.16 - ensure system administrator actions (sudolog) are collected" echo "-w /var/log/sudo.log -p wa -k actions" >> /etc/audit/rules.d/cis.rules echo "4.1.17 - ensure kernel module loading and unloading is collected" echo "-w /sbin/insmod -p x -k modules" >> /etc/audit/rules.d/cis.rules echo "-w /sbin/rmmod -p x -k modules" >> /etc/audit/rules.d/cis.rules echo "-w /sbin/modprobe -p x -k modules" >> /etc/audit/rules.d/cis.rules echo "-a always,exit -F arch=b64 -S init_module -S delete_module -k modules" >> /etc/audit/rules.d/cis.rules echo "4.1.18 - ensure the audit configuration is immutable" echo "-e 2" >> /etc/audit/rules.d/cis.rules echo "4.2.1.1 - ensure rsyslog Service is enabled" yum install -y rsyslog systemctl enable rsyslog echo "4.2.1.2 - ensure logging is configured" echo "*.emerg :omusrmsg:*" >> /etc/rsyslog.d/cis.conf echo "mail.* -/var/log/mail" >> /etc/rsyslog.d/cis.conf echo "mail.info -/var/log/mail.info" >> /etc/rsyslog.d/cis.conf echo "mail.warning -/var/log/mail.warn" >> /etc/rsyslog.d/cis.conf echo "mail.err /var/log/mail.err" >> /etc/rsyslog.d/cis.conf echo "news.crit -/var/log/news/news.crit" >> /etc/rsyslog.d/cis.conf echo "news.err -/var/log/news/news.err" >> /etc/rsyslog.d/cis.conf echo "news.notice -/var/log/news/news.notice" >> /etc/rsyslog.d/cis.conf echo "*.=warning;*.=err -/var/log/warn" >> /etc/rsyslog.d/cis.conf echo "*.crit /var/log/warn" >> /etc/rsyslog.d/cis.conf echo "*.*;mail.none;news.none -/var/log/messages" >> /etc/rsyslog.d/cis.conf echo "local0,local1.* -/var/log/localmessages" >> /etc/rsyslog.d/cis.conf echo "local2,local3.* -/var/log/localmessages" >> /etc/rsyslog.d/cis.conf echo "local4,local5.* -/var/log/localmessages" >> /etc/rsyslog.d/cis.conf echo "local6,local7.* -/var/log/localmessages" >> /etc/rsyslog.d/cis.conf echo "4.2.1.3 - ensure rsyslog default file permissions configured" echo "\$FileCreateMode 0640" >> /etc/rsyslog.d/cis.conf echo "4.2.1.4 - ensure rsyslog is configured to send logs to a remote log host" echo "[not scored] - customer responsible for this configuration" echo "4.2.1.5 - ensure remote rsyslog messages are only accepted on designated log hosts." echo "[not scored] - customer responsible for this configuration" echo "4.2.2.1 - ensure syslog-ng service is enabled" yum install -y syslog-ng systemctl enable syslog-ng && systemctl start syslog-ng echo "4.2.2.2 - Ensure logging is configured" echo "log { source(src); source(chroots); filter(f_console); destination(console); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_console); destination(xconsole); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_newscrit); destination(newscrit); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_newserr); destination(newserr); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_newsnotice); destination(newsnotice); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_mailinfo); destination(mailinfo); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_mailwarn); destination(mailwarn); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_mailerr); destination(mailerr); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_mail); destination(mail); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_acpid); destination(acpid); flags(final); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_acpid_full); destination(devnull); flags(final); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_acpid_old); destination(acpid); flags(final); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_netmgm); destination(netmgm); flags(final); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_local); destination(localmessages); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_messages); destination(messages); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_iptables); destination(firewall); };" >> /etc/syslog-ng/conf.d/cis.conf echo "log { source(src); source(chroots); filter(f_warn); destination(warn); };" >> /etc/syslog-ng/conf.d/cis.conf pkill -HUP syslog-ng echo "4.2.2.3 - ensure syslog-ng default file permissions configured" echo "options { chain_hostnames(off); flush_lines(0); perm(0640); stats_freq(3600); threaded(yes); };" >> /etc/syslog-ng/conf.d/cis.conf echo "4.2.2.4 - ensure syslog-ng is configured to send logs to a remote log host" echo "[not scored] - customer responsible for this configuration" echo "4.2.2.5 - ensure remote syslog-ng messages are only accepted on designated log hosts" echo "[not scored] - customer responsible for this configuration" echo "4.2.3 - ensure rsyslog or syslog-ng is installed" echo "[not scored] - handled by previous steps" echo "4.2.4 - ensure permissions on all logfiles are configured" # Update the systemd unit that produces the dmesg log to have a corrected umask, # which results in correct permissions. cp /usr/lib/systemd/system/rhel-dmesg.service /etc/systemd/system/rhel-dmesg.service sed -i -e '/[Service]/a UMask=0027' /etc/systemd/system/rhel-dmesg.service # Update tmpfiles settings to correct the permissions on the wtmp file: cp /usr/lib/tmpfiles.d/var.conf /etc/tmpfiles.d/var.conf sed -i -e 's|/var/log/wtmp 0664|/var/log/wtmp 0660|' /etc/tmpfiles.d/var.conf systemctl daemon-reload find /var/log -type f -exec chmod g-wx,o-rwx {} + echo "4.3 - ensure logrotate is configured" echo "[not scored] - customer responsible for this configuration" echo "5.1.1 - ensure cron daemon is enabled" systemctl enable crond echo "5.1.2 - ensure permissions on /etc/crontab are configured" chown root:root /etc/crontab chmod og-rwx /etc/crontab echo "5.1.3 - ensure permissions on /etc/cron.hourly are configured" chown root:root /etc/cron.hourly chmod og-rwx /etc/cron.hourly echo "5.1.4 - ensure permissions on /etc/cron.daily are configured" chown root:root /etc/cron.daily chmod og-rwx /etc/cron.daily echo "5.1.5 - ensure permissions on /etc/cron.weekly are configured" chown root:root /etc/cron.weekly chmod og-rwx /etc/cron.weekly echo "5.1.6 - ensure permissions on /etc/cron.monthly are configured" chown root:root /etc/cron.monthly chmod og-rwx /etc/cron.monthly echo "5.1.7 - ensure permissions on /etc/cron.d are configured" chown root:root /etc/cron.d chmod og-rwx /etc/cron.d echo "5.1.8 - ensure at/cron is restricted to authorized users" rm -f /etc/cron.deny rm -f /etc/at.deny touch /etc/cron.allow touch /etc/at.allow chmod og-rwx /etc/cron.allow chmod og-rwx /etc/at.allow chown root:root /etc/cron.allow chown root:root /etc/at.allow echo "5.2.1 - ensure permissions on /etc/ssh/sshd_config are configured" chown root:root /etc/ssh/sshd_config chmod og-rwx /etc/ssh/sshd_config echo "5.2.2 - ensure permissions on SSH private host key files are configured" find /etc/ssh -xdev -type f -name 'ssh_host_*_key' -exec chown root:ssh_keys {} \; find /etc/ssh -xdev -type f -name 'ssh_host_*_key' -exec chmod 0640 {} \; echo "5.2.3 - ensure permissions on SSH public host key files are configured" find /etc/ssh -xdev -type f -name 'ssh_host_*_key.pub' -exec chmod 0644 {} \; find /etc/ssh -xdev -type f -name 'ssh_host_*_key.pub' -exec chown root:root {} \; echo "5.2.3 - 5.2.17, 5.2.19 - SSH Server Configuration" cat > /etc/ssh/sshd_config < /etc/security/pwquality.conf < /etc/pam.d/password-auth < /etc/pam.d/system-auth <> /etc/bashrc echo "umask 027" >> /etc/profile # Just adding the umask isn't enough, all existing entries need to be fixed as # well. sed -i -e 's/\bumask\s\+\(002\|022\)/umask 027/' \ /etc/bashrc /etc/profile /etc/profile.d/*.sh echo "5.4.5 - ensure default user shell timeout is 900 seconds or less" echo "TMOUT=600" >> /etc/bashrc echo "TMOUT=600" >> /etc/profile echo "5.5 - ensure root login is restricted to system console" cat /etc/securetty echo "5.6 - ensure access to the su command is restricted" echo "auth required pam_wheel.so use_uid" >> /etc/pam.d/su echo "6.1.2 - ensure permissions on /etc/passwd are configured" chown root:root /etc/passwd chmod 644 /etc/passwd echo "6.1.3 - ensure permissions on /etc/shadow are configured" chown root:root /etc/shadow chmod 000 /etc/shadow echo "6.1.4 - ensure permissions on /etc/group are configured" chown root:root /etc/group chmod 644 /etc/group echo "6.1.5 - ensure permissions on /etc/gshadow are configured" chown root:root /etc/gshadow chmod 000 /etc/gshadow echo "6.1.6 - ensure permissions on /etc/passwd- are configured" chown root:root /etc/passwd- chmod u-x,go-wx /etc/passwd- echo "6.1.7 - ensure permissions on /etc/shadow- are configured" chown root:root /etc/shadow- chmod 000 /etc/shadow- echo "6.1.8 - ensure permissions on /etc/group- are configured" chown root:root /etc/group- chmod u-x,go-wx /etc/group- echo "6.1.9 - ensure permissions on /etc/gshadow- are configured" chown root:root /etc/gshadow- chmod 000 /etc/gshadow- echo "6.1.10 - ensure no world writable files exist" find / -xdev -type f -perm -0002 echo "6.1.11 - ensure no unowned files or directories exist" find / -xdev -nouser echo "6.1.12 - ensure no ungrouped files or directories exist" find / -xdev -nogroup echo "6.1.13 - audit SUID executables" find / -xdev -type f -perm -4000 echo "6.1.14 - audit SGID executables" find / -xdev -type f -perm -2000 echo "6.2.1 - ensure password fields are not empty" cat /etc/shadow | awk -F: '($2 == "" ) { print $1 " does not have a password "}'