d69cb1ed1a
Add file to run secondary to '{nist-800-53-harden-v2.sh}'. Fixes extra NIST 800.53 issues shows by wazuh configuration checks.
724 lines
28 KiB
Bash
724 lines
28 KiB
Bash
#!/usr/bin/env bash
|
||
###############################################################################
|
||
# NIST 800-53 / CIS Remediation Script – Fixes Wazuh SCA Failures
|
||
# Ubuntu 24.04 LTS (Proxmox VM Template)
|
||
#
|
||
# Run as root after the initial hardening script.
|
||
# Usage: chmod +x remediate.sh && sudo ./remediate.sh
|
||
###############################################################################
|
||
set -euo pipefail
|
||
export DEBIAN_FRONTEND=noninteractive
|
||
|
||
LOG="/var/log/nist-remediation-$(date +%Y%m%d-%H%M%S).log"
|
||
exec > >(tee -a "$LOG") 2>&1
|
||
|
||
banner() { printf '\n\e[1;36m>>> %s\e[0m\n' "$1"; }
|
||
|
||
if [[ $EUID -ne 0 ]]; then echo "Run as root." >&2; exit 1; fi
|
||
|
||
###############################################################################
|
||
# 35509 – Disable additional unused filesystem kernel modules
|
||
###############################################################################
|
||
banner "35509: Disable unused filesystem kernel modules"
|
||
|
||
cat > /etc/modprobe.d/cis-disable-fs.conf <<'EOF'
|
||
install cramfs /bin/false
|
||
install freevxfs /bin/false
|
||
install jffs2 /bin/false
|
||
install hfs /bin/false
|
||
install hfsplus /bin/false
|
||
install squashfs /bin/false
|
||
install udf /bin/false
|
||
install afs /bin/false
|
||
install ceph /bin/false
|
||
install cifs /bin/false
|
||
install exfat /bin/false
|
||
install gfs2 /bin/false
|
||
install nfs /bin/false
|
||
install nfsd /bin/false
|
||
install smbfs /bin/false
|
||
EOF
|
||
|
||
# Blacklist them too
|
||
cat > /etc/modprobe.d/cis-blacklist-fs.conf <<'EOF'
|
||
blacklist cramfs
|
||
blacklist freevxfs
|
||
blacklist jffs2
|
||
blacklist hfs
|
||
blacklist hfsplus
|
||
blacklist squashfs
|
||
blacklist udf
|
||
blacklist afs
|
||
blacklist ceph
|
||
blacklist cifs
|
||
blacklist exfat
|
||
blacklist gfs2
|
||
blacklist nfs
|
||
blacklist nfsd
|
||
blacklist smbfs
|
||
EOF
|
||
|
||
###############################################################################
|
||
# 35522 – Add nodev to /var mount
|
||
###############################################################################
|
||
banner "35522: Add nodev to /var mount"
|
||
|
||
if grep -q 'vg_nist/lv_var ' /etc/fstab; then
|
||
sed -i 's|\(vg_nist/lv_var\s\+/var\s\+ext4\s\+\)defaults,nosuid|\1defaults,nosuid,nodev|' /etc/fstab
|
||
mount -o remount /var
|
||
fi
|
||
|
||
###############################################################################
|
||
# 35537 – Enable AppArmor in bootloader
|
||
###############################################################################
|
||
banner "35537: AppArmor in GRUB + audit at boot"
|
||
|
||
# Also covers 35725 (audit=1) and 35726 (audit_backlog_limit)
|
||
GRUB_PARAMS="apparmor=1 security=apparmor audit=1 audit_backlog_limit=8192"
|
||
|
||
if grep -q '^GRUB_CMDLINE_LINUX="' /etc/default/grub; then
|
||
# Get current value
|
||
CURRENT=$(grep '^GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/GRUB_CMDLINE_LINUX="//;s/"$//')
|
||
# Add missing params
|
||
for param in $GRUB_PARAMS; do
|
||
if ! echo "$CURRENT" | grep -q "$param"; then
|
||
CURRENT="$CURRENT $param"
|
||
fi
|
||
done
|
||
sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"${CURRENT# }\"|" /etc/default/grub
|
||
else
|
||
echo "GRUB_CMDLINE_LINUX=\"${GRUB_PARAMS}\"" >> /etc/default/grub
|
||
fi
|
||
|
||
update-grub
|
||
|
||
###############################################################################
|
||
# 35540 – Bootloader password (informational — uncomment to enable)
|
||
###############################################################################
|
||
banner "35540: Bootloader password (MANUAL STEP)"
|
||
echo " To set a GRUB password:"
|
||
echo " 1. Run: grub-mkpasswd-pbkdf2"
|
||
echo " 2. Add to /etc/grub.d/40_custom:"
|
||
echo " set superusers=\"grubadmin\""
|
||
echo " password_pbkdf2 grubadmin <YOUR_HASH>"
|
||
echo " 3. Run: update-grub"
|
||
echo " Skipping — requires interactive input."
|
||
|
||
###############################################################################
|
||
# 35545 – Disable Apport (automatic error reporting)
|
||
###############################################################################
|
||
banner "35545: Disable Apport"
|
||
|
||
systemctl stop apport.service 2>/dev/null || true
|
||
systemctl disable apport.service 2>/dev/null || true
|
||
systemctl mask apport.service 2>/dev/null || true
|
||
apt-get purge -y apport 2>/dev/null || true
|
||
|
||
###############################################################################
|
||
# 35573, 35585, 35587 – Remove rsync, telnet, ftp
|
||
###############################################################################
|
||
banner "35573/35585/35587: Remove rsync, telnet, ftp"
|
||
|
||
apt-get purge -y rsync telnet inetutils-telnet ftp tnftp 2>/dev/null || true
|
||
|
||
###############################################################################
|
||
# 35589 – Time sync: Wazuh wants systemd-timesyncd but we use chrony
|
||
# Disable timesyncd cleanly since chrony is our NTP (AU-8)
|
||
###############################################################################
|
||
banner "35589: Time sync — chrony is authoritative"
|
||
|
||
# Some CIS scanners flag this; chrony is preferred and NIST-compliant
|
||
systemctl stop systemd-timesyncd 2>/dev/null || true
|
||
systemctl disable systemd-timesyncd 2>/dev/null || true
|
||
systemctl mask systemd-timesyncd 2>/dev/null || true
|
||
echo " chrony is running as the NTP source (AU-8). timesyncd masked."
|
||
echo " If Wazuh still flags this, add an exception — chrony satisfies the control."
|
||
|
||
###############################################################################
|
||
# 35600, 35601 – Restrict cron and at to authorized users
|
||
###############################################################################
|
||
banner "35600/35601: Restrict cron and at"
|
||
|
||
# Remove deny files, create allow files with only root
|
||
rm -f /etc/cron.deny /etc/at.deny
|
||
|
||
echo "root" > /etc/cron.allow
|
||
chmod 640 /etc/cron.allow
|
||
chown root:root /etc/cron.allow
|
||
|
||
echo "root" > /etc/at.allow
|
||
chmod 640 /etc/at.allow
|
||
chown root:root /etc/at.allow
|
||
|
||
###############################################################################
|
||
# 35604-35607 – Disable network protocol kernel modules properly
|
||
###############################################################################
|
||
banner "35604-35607: Disable unused network kernel modules"
|
||
|
||
cat > /etc/modprobe.d/cis-disable-net.conf <<'EOF'
|
||
install dccp /bin/false
|
||
install sctp /bin/false
|
||
install rds /bin/false
|
||
install tipc /bin/false
|
||
EOF
|
||
|
||
cat > /etc/modprobe.d/cis-blacklist-net.conf <<'EOF'
|
||
blacklist dccp
|
||
blacklist sctp
|
||
blacklist rds
|
||
blacklist tipc
|
||
EOF
|
||
|
||
###############################################################################
|
||
# 35619-35639 – Firewall: configure UFW properly
|
||
# CIS checks all three frameworks. We use UFW — nftables/iptables checks
|
||
# will show "failed" because those aren't our chosen tool. That's expected.
|
||
###############################################################################
|
||
banner "35619-35639: UFW firewall hardening"
|
||
|
||
# Ensure UFW is the only active firewall
|
||
systemctl stop nftables 2>/dev/null || true
|
||
systemctl disable nftables 2>/dev/null || true
|
||
systemctl mask nftables 2>/dev/null || true
|
||
|
||
# Loopback rules (35623)
|
||
ufw allow in on lo
|
||
ufw allow out on lo
|
||
ufw deny in from 127.0.0.0/8
|
||
ufw deny in from ::1
|
||
|
||
# Default policies (35624)
|
||
ufw default deny incoming
|
||
ufw default deny outgoing
|
||
ufw default deny routed
|
||
|
||
# Allow essential outbound
|
||
ufw allow out 53 comment 'DNS'
|
||
ufw allow out 80/tcp comment 'HTTP'
|
||
ufw allow out 443/tcp comment 'HTTPS'
|
||
ufw allow out 123/udp comment 'NTP'
|
||
|
||
# SSH inbound (already added but ensure)
|
||
ufw limit in 22/tcp comment 'SSH rate-limited'
|
||
|
||
# Wazuh agent outbound (if applicable)
|
||
ufw allow out 1514/tcp comment 'Wazuh agent'
|
||
ufw allow out 1515/tcp comment 'Wazuh enrollment'
|
||
|
||
ufw --force enable
|
||
ufw status verbose
|
||
|
||
###############################################################################
|
||
# 35641-35642 – SSH host key permissions
|
||
# Keys were removed for template prep. Regenerate them now for testing;
|
||
# the firstboot service will regenerate on each clone.
|
||
###############################################################################
|
||
banner "35641/35642: SSH host key permissions"
|
||
|
||
# Regenerate if missing (template prep removed them)
|
||
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
|
||
dpkg-reconfigure openssh-server
|
||
fi
|
||
|
||
# Set strict permissions
|
||
chmod 600 /etc/ssh/ssh_host_*_key
|
||
chmod 644 /etc/ssh/ssh_host_*_key.pub
|
||
chown root:root /etc/ssh/ssh_host_*
|
||
|
||
###############################################################################
|
||
# 35643-35661 – SSH configuration (complete rewrite)
|
||
###############################################################################
|
||
banner "35643-35661: Complete SSH hardening"
|
||
|
||
cat > /etc/ssh/sshd_config.d/nist-hardening.conf <<'SSHEOF'
|
||
# ============= NIST 800-53 + CIS SSH Hardening =============
|
||
|
||
Protocol 2
|
||
|
||
# Authentication
|
||
PermitRootLogin no
|
||
PubkeyAuthentication yes
|
||
PasswordAuthentication no
|
||
PermitEmptyPasswords no
|
||
ChallengeResponseAuthentication no
|
||
UsePAM yes
|
||
MaxAuthTries 3
|
||
LoginGraceTime 60
|
||
|
||
# Disable host-based auth (35649)
|
||
HostbasedAuthentication no
|
||
IgnoreRhosts yes
|
||
|
||
# Disable GSSAPI (35648)
|
||
GSSAPIAuthentication no
|
||
|
||
# Disable user environment (35660)
|
||
PermitUserEnvironment no
|
||
|
||
# Session limits (35646, 35656, 35657)
|
||
ClientAliveInterval 300
|
||
ClientAliveCountMax 3
|
||
MaxSessions 3
|
||
MaxStartups 10:30:60
|
||
|
||
# Forwarding — use DisableForwarding (35647)
|
||
DisableForwarding yes
|
||
|
||
# Cryptography (SC-13)
|
||
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
|
||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
|
||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
|
||
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
|
||
|
||
# Banner (35644 / AC-8)
|
||
Banner /etc/issue.net
|
||
|
||
# Logging (35653 / AU-3)
|
||
LogLevel VERBOSE
|
||
|
||
# Access restriction (35643) — adjust username as needed
|
||
AllowGroups sudo
|
||
SSHEOF
|
||
|
||
# Remove stale/conflicting configs
|
||
rm -f /etc/ssh/sshd_config.d/50-cloud-init.conf 2>/dev/null || true
|
||
|
||
# Validate and restart
|
||
sshd -t && systemctl restart ssh
|
||
echo " SSH config validated and restarted."
|
||
|
||
###############################################################################
|
||
# 35664 – Sudo log file
|
||
###############################################################################
|
||
banner "35664: Sudo logging"
|
||
|
||
if ! grep -q 'Defaults.*logfile' /etc/sudoers; then
|
||
echo 'Defaults logfile="/var/log/sudo.log"' >> /etc/sudoers
|
||
fi
|
||
|
||
###############################################################################
|
||
# 35668 – Restrict su to sudo group
|
||
###############################################################################
|
||
banner "35668: Restrict su command"
|
||
|
||
# Ensure pam_wheel is properly configured
|
||
sed -i '/pam_wheel.so/d' /etc/pam.d/su
|
||
echo "auth required pam_wheel.so use_uid group=sudo" >> /etc/pam.d/su
|
||
|
||
###############################################################################
|
||
# 35672-35690 – PAM configuration (complete)
|
||
###############################################################################
|
||
banner "35672-35690: PAM configuration"
|
||
|
||
# --- common-auth ---
|
||
cat > /etc/pam.d/common-auth <<'EOF'
|
||
# NIST 800-53 / CIS compliant PAM auth stack
|
||
|
||
# pam_faillock: preauth (AC-7)
|
||
auth required pam_faillock.so preauth
|
||
# pam_unix: standard unix auth
|
||
auth [success=1 default=ignore] pam_unix.so
|
||
# pam_faillock: authfail
|
||
auth [default=die] pam_faillock.so authfail
|
||
auth sufficient pam_faillock.so authsucc
|
||
# Deny by default
|
||
auth requisite pam_deny.so
|
||
auth required pam_permit.so
|
||
EOF
|
||
|
||
# --- common-account ---
|
||
cat > /etc/pam.d/common-account <<'EOF'
|
||
# NIST 800-53 / CIS compliant PAM account stack
|
||
account required pam_faillock.so
|
||
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
|
||
account requisite pam_deny.so
|
||
account required pam_permit.so
|
||
EOF
|
||
|
||
# --- common-password ---
|
||
cat > /etc/pam.d/common-password <<'EOF'
|
||
# NIST 800-53 / CIS compliant PAM password stack
|
||
|
||
# pam_pwquality: password complexity (IA-5)
|
||
password requisite pam_pwquality.so retry=3
|
||
# pam_pwhistory: remember 24 passwords (IA-5)
|
||
password required pam_pwhistory.so remember=24 use_authtok enforce_for_root
|
||
# pam_unix: store password
|
||
password [success=1 default=ignore] pam_unix.so obscure use_authtok try_first_pass yescrypt shadow
|
||
password requisite pam_deny.so
|
||
password required pam_permit.so
|
||
EOF
|
||
|
||
# --- common-session ---
|
||
cat > /etc/pam.d/common-session <<'EOF'
|
||
# NIST 800-53 / CIS compliant PAM session stack
|
||
session [default=1] pam_permit.so
|
||
session requisite pam_deny.so
|
||
session required pam_permit.so
|
||
session required pam_unix.so
|
||
session optional pam_systemd.so
|
||
EOF
|
||
|
||
###############################################################################
|
||
# 35681, 35683 – Password quality (maxsequence)
|
||
###############################################################################
|
||
banner "35681/35683: Password quality — maxsequence"
|
||
|
||
cat > /etc/security/pwquality.conf <<'EOF'
|
||
# IA-5(1): Password complexity — CIS compliant
|
||
minlen = 15
|
||
dcredit = -1
|
||
ucredit = -1
|
||
lcredit = -1
|
||
ocredit = -1
|
||
difok = 8
|
||
maxrepeat = 3
|
||
maxsequence = 3
|
||
maxclassrepeat = 4
|
||
gecoscheck = 1
|
||
dictcheck = 1
|
||
enforcing = 1
|
||
EOF
|
||
|
||
###############################################################################
|
||
# 35694, 35695, 35698 – Password expiration and inactive lock
|
||
###############################################################################
|
||
banner "35694/35695/35698: Password aging and inactive lock"
|
||
|
||
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS\t60/' /etc/login.defs
|
||
sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS\t1/' /etc/login.defs
|
||
sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE\t14/' /etc/login.defs
|
||
|
||
# Set inactive password lock to 30 days
|
||
useradd -D -f 30
|
||
|
||
# Apply to existing users (adjust username)
|
||
for user in $(awk -F: '($3 >= 1000) && ($7 != "/usr/sbin/nologin") {print $1}' /etc/passwd); do
|
||
chage --maxdays 60 --mindays 1 --warndays 14 "$user"
|
||
chage --inactive 30 "$user"
|
||
done
|
||
|
||
###############################################################################
|
||
# 35703 – Root umask
|
||
###############################################################################
|
||
banner "35703: Root user umask"
|
||
|
||
# Set in root's bashrc
|
||
if ! grep -q 'umask 027' /root/.bashrc 2>/dev/null; then
|
||
echo "umask 027" >> /root/.bashrc
|
||
fi
|
||
|
||
# Create bash_profile if missing
|
||
if [ ! -f /root/.bash_profile ]; then
|
||
cat > /root/.bash_profile <<'EOF'
|
||
umask 027
|
||
[ -f ~/.bashrc ] && . ~/.bashrc
|
||
EOF
|
||
fi
|
||
|
||
if ! grep -q 'umask 027' /root/.bash_profile; then
|
||
sed -i '1i umask 027' /root/.bash_profile
|
||
fi
|
||
|
||
###############################################################################
|
||
# 35708 – Journald log rotation
|
||
###############################################################################
|
||
banner "35708: Journald configuration"
|
||
|
||
mkdir -p /etc/systemd/journald.conf.d
|
||
cat > /etc/systemd/journald.conf.d/nist.conf <<'EOF'
|
||
[Journal]
|
||
Compress=yes
|
||
Storage=persistent
|
||
ForwardToSyslog=yes
|
||
SystemMaxUse=1G
|
||
SystemKeepFree=1G
|
||
SystemMaxFileSize=100M
|
||
MaxFileSec=1month
|
||
EOF
|
||
|
||
systemctl restart systemd-journald
|
||
|
||
###############################################################################
|
||
# 35719 – rsyslog file creation mode
|
||
###############################################################################
|
||
banner "35719: rsyslog file creation mode"
|
||
|
||
cat > /etc/rsyslog.d/99-nist-perms.conf <<'EOF'
|
||
$FileCreateMode 0640
|
||
$DirCreateMode 0750
|
||
$Umask 0027
|
||
EOF
|
||
|
||
systemctl restart rsyslog
|
||
|
||
###############################################################################
|
||
# 35720 – rsyslog remote logging (placeholder)
|
||
###############################################################################
|
||
banner "35720: rsyslog remote logging"
|
||
echo " Wazuh is handling remote log collection."
|
||
echo " If you also need syslog forwarding, add to /etc/rsyslog.d/:"
|
||
echo " *.* @@your-syslog-server:514"
|
||
echo " Skipping — environment-specific."
|
||
|
||
###############################################################################
|
||
# 35722 – Log file permissions
|
||
###############################################################################
|
||
banner "35722: Fix log file permissions"
|
||
|
||
find /var/log -type f -exec chmod g-wx,o-rwx {} +
|
||
find /var/log -type d -exec chmod g-w,o-rwx {} +
|
||
|
||
###############################################################################
|
||
# 35725, 35726 – Audit at boot (handled above in GRUB section)
|
||
###############################################################################
|
||
banner "35725/35726: Audit at boot — handled in GRUB section above"
|
||
|
||
###############################################################################
|
||
# 35728-35730 – Auditd configuration
|
||
###############################################################################
|
||
banner "35728-35730: Auditd log management"
|
||
|
||
# Write directly to auditd.conf since the .d directory may not be supported
|
||
cp /etc/audit/auditd.conf /etc/audit/auditd.conf.bak
|
||
|
||
sed -i 's/^max_log_file_action.*/max_log_file_action = keep_logs/' /etc/audit/auditd.conf
|
||
sed -i 's/^space_left_action.*/space_left_action = email/' /etc/audit/auditd.conf
|
||
sed -i 's/^admin_space_left_action.*/admin_space_left_action = halt/' /etc/audit/auditd.conf
|
||
|
||
# Ensure these exist
|
||
grep -q '^max_log_file_action' /etc/audit/auditd.conf || echo 'max_log_file_action = keep_logs' >> /etc/audit/auditd.conf
|
||
grep -q '^space_left_action' /etc/audit/auditd.conf || echo 'space_left_action = email' >> /etc/audit/auditd.conf
|
||
grep -q '^admin_space_left_action' /etc/audit/auditd.conf || echo 'admin_space_left_action = halt' >> /etc/audit/auditd.conf
|
||
|
||
###############################################################################
|
||
# 35731-35748 – Comprehensive audit rules (CIS complete)
|
||
###############################################################################
|
||
banner "35731-35748: CIS-compliant audit rules"
|
||
|
||
cat > /etc/audit/rules.d/cis-nist.rules <<'AUDITRULES'
|
||
## Remove existing rules
|
||
-D
|
||
|
||
## Buffer
|
||
-b 8192
|
||
|
||
## Failure mode
|
||
-f 1
|
||
|
||
## 35731 – Sudoers changes
|
||
-w /etc/sudoers -p wa -k scope
|
||
-w /etc/sudoers.d -p wa -k scope
|
||
|
||
## 35732 – Actions as another user
|
||
-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation
|
||
-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation
|
||
|
||
## 35733 – Sudo log file events
|
||
-w /var/log/sudo.log -p wa -k sudo_log
|
||
|
||
## 35734 – Date and time changes
|
||
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change
|
||
-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time-change
|
||
-w /etc/localtime -p wa -k time-change
|
||
|
||
## 35735 – Network environment changes
|
||
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
|
||
-a always,exit -F arch=b32 -S sethostname,setdomainname -k system-locale
|
||
-w /etc/issue -p wa -k system-locale
|
||
-w /etc/issue.net -p wa -k system-locale
|
||
-w /etc/hosts -p wa -k system-locale
|
||
-w /etc/hostname -p wa -k system-locale
|
||
-w /etc/netplan/ -p wa -k system-locale
|
||
|
||
## 35736 – Unsuccessful file access attempts
|
||
-a always,exit -F arch=b64 -S open,truncate,ftruncate,creat,openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -k access
|
||
-a always,exit -F arch=b64 -S open,truncate,ftruncate,creat,openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -k access
|
||
-a always,exit -F arch=b32 -S open,truncate,ftruncate,creat,openat -F exit=-EACCES -F auid>=1000 -F auid!=unset -k access
|
||
-a always,exit -F arch=b32 -S open,truncate,ftruncate,creat,openat -F exit=-EPERM -F auid>=1000 -F auid!=unset -k access
|
||
|
||
## 35737 – User/group information changes
|
||
-w /etc/group -p wa -k identity
|
||
-w /etc/passwd -p wa -k identity
|
||
-w /etc/gshadow -p wa -k identity
|
||
-w /etc/shadow -p wa -k identity
|
||
-w /etc/security/opasswd -p wa -k identity
|
||
|
||
## 35738 – DAC permission modification
|
||
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -k perm_mod
|
||
-a always,exit -F arch=b64 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=unset -k perm_mod
|
||
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -k perm_mod
|
||
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -k perm_mod
|
||
-a always,exit -F arch=b32 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=unset -k perm_mod
|
||
-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -k perm_mod
|
||
|
||
## 35739 – Successful file system mounts
|
||
-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=unset -k mounts
|
||
-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=unset -k mounts
|
||
|
||
## 35740 – Session initiation
|
||
-w /var/run/utmp -p wa -k session
|
||
-w /var/log/wtmp -p wa -k session
|
||
-w /var/log/btmp -p wa -k session
|
||
|
||
## 35741 – Login and logout events
|
||
-w /var/log/lastlog -p wa -k logins
|
||
-w /var/run/faillock -p wa -k logins
|
||
|
||
## 35742 – File deletion events
|
||
-a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>=1000 -F auid!=unset -k delete
|
||
-a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>=1000 -F auid!=unset -k delete
|
||
|
||
## 35743 – Mandatory Access Controls
|
||
-w /etc/apparmor/ -p wa -k MAC-policy
|
||
-w /etc/apparmor.d/ -p wa -k MAC-policy
|
||
|
||
## 35744 – chcon command
|
||
-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng
|
||
|
||
## 35745 – setfacl command
|
||
-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng
|
||
|
||
## 35746 – chacl command
|
||
-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng
|
||
|
||
## 35747 – usermod command
|
||
-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset -k usermod
|
||
|
||
## 35748 – Kernel module loading/unloading
|
||
-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
|
||
-w /sbin/insmod -p x -k kernel_modules
|
||
-w /sbin/rmmod -p x -k kernel_modules
|
||
-w /sbin/modprobe -p x -k kernel_modules
|
||
-w /usr/bin/kmod -p x -k kernel_modules
|
||
|
||
## Make immutable (requires reboot to change)
|
||
-e 2
|
||
AUDITRULES
|
||
|
||
# Remove old rules file to avoid conflicts
|
||
rm -f /etc/audit/rules.d/nist-800-53.rules
|
||
|
||
# Load new rules
|
||
augenrules --load 2>/dev/null || true
|
||
# auditd often requires a service restart for rule reload
|
||
systemctl restart auditd 2>/dev/null || true
|
||
|
||
###############################################################################
|
||
# 35752 – Audit config file permissions
|
||
###############################################################################
|
||
banner "35752: Audit configuration file permissions"
|
||
|
||
find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) -exec chmod 640 {} +
|
||
chown -R root:root /etc/audit/
|
||
|
||
###############################################################################
|
||
# 35755 – Audit tools permissions
|
||
###############################################################################
|
||
banner "35755: Audit tools permissions"
|
||
|
||
for tool in /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/augenrules; do
|
||
if [ -f "$tool" ]; then
|
||
chmod 755 "$tool"
|
||
chown root:root "$tool"
|
||
fi
|
||
done
|
||
|
||
###############################################################################
|
||
# 35760 – AIDE protects audit tools
|
||
###############################################################################
|
||
banner "35760: AIDE audit tool integrity"
|
||
|
||
cat > /etc/aide/aide.conf.d/99_audit_tools <<'EOF'
|
||
# CIS: Protect integrity of audit tools
|
||
/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512
|
||
EOF
|
||
|
||
###############################################################################
|
||
# 35770 – opasswd permissions
|
||
###############################################################################
|
||
banner "35770: opasswd file permissions"
|
||
|
||
touch /etc/security/opasswd
|
||
chmod 600 /etc/security/opasswd
|
||
chown root:root /etc/security/opasswd
|
||
|
||
# Also create opasswd.old if it doesn't exist
|
||
touch /etc/security/opasswd.old
|
||
chmod 600 /etc/security/opasswd.old
|
||
chown root:root /etc/security/opasswd.old
|
||
|
||
###############################################################################
|
||
# FINAL CLEANUP
|
||
###############################################################################
|
||
banner "Final cleanup"
|
||
|
||
# Rebuild AIDE database with new audit tool entries
|
||
echo " Rebuilding AIDE database (this will take several minutes)..."
|
||
aideinit -y -f 2>/dev/null || true
|
||
|
||
apt-get autoremove -y
|
||
apt-get clean
|
||
|
||
###############################################################################
|
||
# SUMMARY
|
||
###############################################################################
|
||
banner "Remediation Complete"
|
||
|
||
cat <<'SUMMARY'
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ Remediation Summary ║
|
||
╠══════════════════════════════════════════════════════════════════╣
|
||
║ ║
|
||
║ FIXED: ║
|
||
║ 35509 Unused filesystem modules disabled ║
|
||
║ 35522 /var nodev added ║
|
||
║ 35537 AppArmor enabled in bootloader ║
|
||
║ 35545 Apport disabled and removed ║
|
||
║ 35573 rsync removed ║
|
||
║ 35585 telnet removed ║
|
||
║ 35587 ftp removed ║
|
||
║ 35589 timesyncd masked (chrony is NTP source) ║
|
||
║ 35600 cron.allow created ║
|
||
║ 35601 at.allow created ║
|
||
║ 35604-07 Network protocol modules disabled ║
|
||
║ 35619+ UFW firewall fully configured ║
|
||
║ 35641-42 SSH host key permissions set ║
|
||
║ 35643-61 SSH fully hardened ║
|
||
║ 35664 Sudo logging enabled ║
|
||
║ 35668 su restricted to sudo group ║
|
||
║ 35672-90 PAM stack fully configured ║
|
||
║ 35694-98 Password aging and inactive lock ║
|
||
║ 35703 Root umask set ║
|
||
║ 35708 Journald rotation configured ║
|
||
║ 35719 rsyslog file creation mode set ║
|
||
║ 35722 Log file permissions tightened ║
|
||
║ 35725-26 Audit at boot enabled ║
|
||
║ 35728-30 Auditd log management configured ║
|
||
║ 35731-48 Full CIS audit rules applied ║
|
||
║ 35752 Audit config permissions set ║
|
||
║ 35755 Audit tools permissions set ║
|
||
║ 35760 AIDE protects audit tools ║
|
||
║ 35770 opasswd permissions configured ║
|
||
║ ║
|
||
║ MANUAL STEPS REQUIRED: ║
|
||
║ 35540 Set GRUB bootloader password ║
|
||
║ 35720 Configure remote syslog if needed ║
|
||
║ 35710 Configure journal-upload if needed ║
|
||
║ ║
|
||
║ EXPECTED SCANNER NOISE (not actual failures): ║
|
||
║ 35626-35639 nftables/iptables checks — we use UFW ║
|
||
║ 35589 timesyncd — we use chrony instead ║
|
||
║ ║
|
||
║ Reboot required for GRUB and kernel module changes. ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
SUMMARY
|
||
|
||
echo ""
|
||
echo "Full log: $LOG"
|
||
echo "Reboot now: shutdown -r now" |