Files
NIST-800.53-VM/remediate.sh
T
chris d69cb1ed1a Add '{remediate.sh}'
Add file to run secondary to '{nist-800-53-harden-v2.sh}'.  Fixes extra NIST 800.53 issues shows by wazuh configuration checks.
2026-05-28 02:49:25 +00:00

724 lines
28 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"