diff --git a/arch-hardening.sh b/arch-hardening.sh index ad01bd4..2075ded 100644 --- a/arch-hardening.sh +++ b/arch-hardening.sh @@ -1,14 +1,22 @@ #!/bin/bash +log() { + echo "[$(date --rfc-3339=seconds)] $*" >&2 +} + +# Update system +log "Updating system packages..." +sudo pacman -Syu --noconfirm + # [STRG-1846] Disable drivers like firewire -sudo tee /etc/modprobe.d/firewire-disable.conf > /dev/null </dev/null < /dev/null +echo 'DNSSEC=yes' | sudo tee -a /etc/systemd/resolved.conf >/dev/null sudo systemctl restart systemd-resolved # [USB-3000] Ensure USBGUARD is installed and configured sudo pacman -S --noconfirm --needed usbguard -sudo usbguard generate-policy | sudo tee /etc/usbguard/rules.conf > /dev/null +sudo usbguard generate-policy | sudo tee /etc/usbguard/rules.conf >/dev/null sudo sed -i 's/^PresentControllerPolicy=.*/PresentControllerPolicy=apply-policy/' /etc/usbguard/usbguard-daemon.conf sudo systemctl enable --now usbguard @@ -31,13 +39,14 @@ sudo pacman -S --noconfirm --needed arpwatch # Find first non-loopback, non-virbr/vmbr interface and enable arpwatch on it iface=$(ip -o link show | awk -F': ' '{print $2}' | sed 's/@.*$//' | grep -Ev '^(lo|virbr|vmbr)' | head -n1) if [ -n "$iface" ]; then - sudo systemctl enable --now "arpwatch@${iface}.service" + sudo systemctl enable --now "arpwatch@${iface}.service" else - echo "No suitable network interface found for arpwatch; service not enabled." >&2 + echo "No suitable network interface found for arpwatch; service not enabled." >&2 fi # [NETW-3200] Disable unused network protocols -sudo tee /etc/modprobe.d/network-protocols-disable.conf > /dev/null </dev/null < /dev/null -sudo echo 'SCRIPTWHITELIST=/usr/bin/fgrep' | sudo tee -a /etc/rkhunter.conf > /dev/null -sudo echo 'SCRIPTWHITELIST=/usr/bin/ldd' | sudo tee -a /etc/rkhunter.conf > /dev/null -sudo echo 'SCRIPTWHITELIST=/usr/bin/rkhunter' | sudo tee -a /etc/rkhunter.conf > /dev/null +#sudo pacman -S --noconfirm --needed rkhunter +#sudo rkhunter --propupd +#sudo echo 'SCRIPTWHITELIST=/usr/bin/egrep' | sudo tee -a /etc/rkhunter.conf >/dev/null +#sudo echo 'SCRIPTWHITELIST=/usr/bin/fgrep' | sudo tee -a /etc/rkhunter.conf >/dev/null +#sudo echo 'SCRIPTWHITELIST=/usr/bin/ldd' | sudo tee -a /etc/rkhunter.conf >/dev/null +#sudo echo 'SCRIPTWHITELIST=/usr/bin/rkhunter' | sudo tee -a /etc/rkhunter.conf >/dev/null # [MALW-3282] Ensure ClamAV is installed sudo pacman -S --noconfirm --needed clamav +sudo systemctl enable --now clamav-daemon clamav-freshclam sudo freshclam -sudo systemctl enable --now clamav-freshclam -sleep 5 -sudo systemctl enable --now clamav-daemon # [FINT-4350] Install a file integrity tool sudo pacman -S --noconfirm --needed aide @@ -75,12 +82,10 @@ sudo systemctl enable --now aidecheck.timer # [FIRE-45XX] Firewall configuration # remove iptables if installed -if pacman -Qi iptables &> /dev/null; then - sudo pacman -R --noconfirm iptables -fi -sudo pacman -S --noconfirm --needed nftables - -sudo tee /etc/modprobe.d/ip_tables-disable.conf > /dev/null </dev/null < /dev/null <<'EOL' +sudo tee /etc/systemd/coredump.conf.d/99-disable-coredumps.conf >/dev/null <<'EOL' [Coredump] # Prevent any core file data being stored and limit accepted size to 0 ProcessSizeMax=0 @@ -103,22 +107,22 @@ EOL sudo systemctl daemon-reload sudo mkdir -p /etc/security/limits.d/ -sudo tee /etc/security/limits.d/20-disable-core-dumps.conf > /dev/null </dev/null < * hard core 0 * soft core 0 EOL # Append to /etc/profile to enforce core dump restriction system-wide -echo '# Disable core dumps system-wide' | sudo tee -a /etc/profile > /dev/null -echo 'ulimit -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null -echo '# Set the core dump soft limit to 0 (current enforceable limit)' | sudo tee -a /etc/profile > /dev/null -echo 'ulimit -S -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null -echo '# Set the hard limit to 0 (absolute maximum limit)' | sudo tee -a /etc/profile > /dev/null -echo 'ulimit -H -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null +if ! grep -q "ulimit -c 0" /etc/profile 2>/dev/null; then + echo '# Disable core dumps system-wide' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -S -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -H -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null +fi # [KRNL-6000] Check sysctl settings for kernel hardening -sudo tee /etc/sysctl.d/99-hardened.conf > /dev/null <<'EOL' +sudo tee /etc/sysctl.d/99-hardened.conf >/dev/null <<'EOL' # Kernel and filesystem hardening settings kernel.randomize_va_space = 2 kernel.kptr_restrict = 2 @@ -140,22 +144,30 @@ net.core.bpf_jit_harden = 2 net.ipv4.conf.all.forwarding = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 +net.ipv4.conf.default.send_redirects = 0 net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.default.log_martians = 1 +net.ipv4.conf.all.secure_redirects = 0 +net.ipv4.conf.default.secure_redirects = 0 +net.ipv4.conf.all.rp_filter = 1 +net.ipv4.conf.default.rp_filter = 1 + net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 +net.ipv6.conf.all.accept_ra = 0 +net.ipv6.conf.default.accept_ra = 0 EOL sudo sysctl --system # [SHLL-6220] Idle session handling -echo 'TMOUT=900' | sudo tee -a /etc/profile > /dev/null -echo 'readonly TMOUT' | sudo tee -a /etc/profile > /dev/null -echo 'export TMOUT' | sudo tee -a /etc/profile > /dev/null +echo 'TMOUT=900' | sudo tee -a /etc/profile >/dev/null +echo 'readonly TMOUT' | sudo tee -a /etc/profile >/dev/null +echo 'export TMOUT' | sudo tee -a /etc/profile >/dev/null # [MACF-6290] Enable MAC framework (AppArmor) sudo pacman -S --noconfirm --needed apparmor apparmor.d-git @@ -164,46 +176,57 @@ sudo systemctl enable --now apparmor # [FILE-6344] Restricting process details to users ## Editing fstab if ! grep -q '^proc\s\+/proc\s\+proc\s\+' /etc/fstab; then - echo '# /proc' | sudo tee -a /etc/fstab > /dev/null - echo 'proc /proc proc defaults,hidepid=2,gid=wheel 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /proc' | sudo tee -a /etc/fstab >/dev/null + echo 'proc /proc proc defaults,hidepid=2,gid=wheel 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^proc[[:space:]]\+/proc[[:space:]]\+proc[[:space:]]\+.*$|proc /proc proc defaults,hidepid=1,gid=wheel 0 0|' /etc/fstab + sudo sed -i 's|^proc[[:space:]]\+/proc[[:space:]]\+proc[[:space:]]\+.*$|proc /proc proc defaults,hidepid=1,gid=wheel 0 0|' /etc/fstab fi ## Remount /proc to apply changes immediately sudo systemctl daemon-reload sudo mount -o remount /proc -# [FILE-6374] Check mount options -# if /dev/shm is not in /etc/fstab, add it with the correct options -if ! grep -q '^tmpfs\s\+/dev/shm\s\+tmpfs\s\+' /etc/fstab; then - echo '# /dev/shm' | sudo tee -a /etc/fstab > /dev/null - echo 'tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab > /dev/null +# [FILE-6374] Check /dev, /dev/shm and /tmp mount options +log "Ensuring /dev, /dev/shm and /tmp have secure mount options..." + +if ! grep -q '^devtmpfs\s\+/dev\s\+devtmpfs\s\+' /etc/fstab; then + echo '# /dev' | sudo tee -a /etc/fstab >/dev/null + echo 'devtmpfs /dev devtmpfs rw,nosuid,noexec,relatime,size=10%,mode=755 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^tmpfs[[:space:]]\+/dev/shm[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab + sudo sed -i 's|^devtmpfs[[:space:]]\+/dev[[:space:]]\+devtmpfs[[:space:]]\+.*$|devtmpfs /dev devtmpfs rw,nosuid,noexec,relatime,size=10%,mode=755 0 0|' /etc/fstab +fi +sudo systemctl daemon-reload +sudo mount -o remount /dev + +if ! grep -q '^tmpfs\s\+/dev/shm\s\+tmpfs\s\+' /etc/fstab; then + echo '# /dev/shm' | sudo tee -a /etc/fstab >/dev/null + echo 'tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab >/dev/null +else + sudo sed -i 's|^tmpfs[[:space:]]\+/dev/shm[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab fi -# Remount /dev/shm to apply changes immediately sudo systemctl daemon-reload sudo mount -o remount /dev/shm -# Replace /tmp mount if ! grep -q '^tmpfs\s\+/tmp\s\+tmpfs\s\+' /etc/fstab; then - echo '# /tmp' | sudo tee -a /etc/fstab > /dev/null - echo 'tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /tmp' | sudo tee -a /etc/fstab >/dev/null + echo 'tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^tmpfs[[:space:]]\+/tmp[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab + sudo sed -i 's|^tmpfs[[:space:]]\+/tmp[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab fi -# Remount /tmp to apply changes immediately sudo systemctl daemon-reload sudo mount -o remount /tmp # [FILE-6430] Disable mounting of some filesystems -sudo tee /etc/modprobe.d/fs_blacklist.conf > /dev/null </dev/null < /dev/null </dev/null < /dev/null </dev/null <> /etc/pacman.conf' - fi + if sudo grep -qE '^[[:space:]]*NoExtract' /etc/pacman.conf; then + sudo sed -i '0,/^[[:space:]]*NoExtract/ s|^\([[:space:]]*NoExtract[[:space:]]*=[[:space:]]*\)\(.*\)$|\1\2 usr/bin/as|' /etc/pacman.conf + elif sudo grep -qE '^[[:space:]]*#[[:space:]]*NoExtract' /etc/pacman.conf; then + sudo sed -i '/^[[:space:]]*#[[:space:]]*NoExtract/ a NoExtract = usr/bin/as' /etc/pacman.conf + else + sudo bash -c 'printf "\n# NoExtract added by hardening script\nNoExtract = usr/bin/as\n" >> /etc/pacman.conf' + fi fi # [HRDN-7222] Restricting compilator access to root user only @@ -280,7 +326,7 @@ sudo systemctl enable --now rngd #sudo systemctl enable --now haveged # [CRYP-8006] Ensure MemoryOverwriteRequest-bit set -sudo tee /usr/lib/systemd/system-shutdown/mor-bit-wipe.shutdown > /dev/null <<'EOL' +sudo tee /usr/lib/systemd/system-shutdown/mor-bit-wipe.shutdown >/dev/null <<'EOL' #!/bin/bash # Path to the MemoryOverwriteRequestControl UEFI variable @@ -288,8 +334,11 @@ MOR_VAR_PATH="/sys/firmware/efi/efivars/MemoryOverwriteRequestControl-e20939be-3 # Check if the UEFI variable path exists if [ -e "$MOR_VAR_PATH" ]; then - # The expected format is: Attributes (4 bytes) + Value (1 byte for MOR state) - # We need to write 5 bytes in total: 0x07 0x00 0x00 0x00 (Attributes) + 0x01 (MOR-bit set) + # The expected format is: Attributes (4 bytes) + Value (1 byte for MOR state) + # We need to write 5 bytes in total: 0x07 0x00 0x00 0x00 (Attributes) + 0x01 (MOR-bit set) + + # Removing immutable on the efi variable + chattr -i "$MOR_VAR" 2>/dev/null # Use printf to create the necessary 5-byte data and write it to the variable # 0x01 means MOR is SET (request memory wipe) @@ -310,16 +359,26 @@ sudo sed -i 's/^#SHA_CRYPT_MAX_ROUNDS .*/SHA_CRYPT_MAX_ROUNDS 5000000/' /etc/log # [AUTH-9262] Password strength checking tool is installed sudo pacman -S --noconfirm --needed libpwquality -sudo tee /etc/security/pwquality.conf > /dev/null <> /etc/security/pwquality.conf" + fi +} + +set_pwq "retry" 3 +set_pwq "difok" 6 +set_pwq "minlen" 14 +set_pwq "dcredit" -1 +set_pwq "ucredit" -1 +set_pwq "ocredit" -1 +set_pwq "lcredit" -1 +set_pwq "minclass" 4 +set_pwq "usercheck" 1 +set_pwq "enforcing" 1 sudo sed -i '/^password\s*required\s*pam_unix.so\s*try_first_pass\s*nullok\s*shadow/i password required pam_pwquality.so' /etc/pam.d/system-auth @@ -328,23 +387,27 @@ sudo sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 7/' /etc/login.defs sudo sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs # [AUTH-9328] Ensure default user umask is 027 or more restrictive -sudo sed -i 's/^UMASK.*/UMASK 027/' /etc/login.defs -if sudo grep -qE '^[[:space:]]*#?[[:space:]]*umask' /etc/bash.bashrc; then - sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/bash.bashrc +if sudo grep -Eq '^[[:space:]]*#?[[:space:]]*UMASK\b' /etc/login.defs 2>/dev/null; then + sudo sed -ri "s|^[[:space:]]*#?[[:space:]]*UMASK[[:space:]]+.*|UMASK 027|" /etc/login.defs || true else - echo 'umask 027' | sudo tee -a /etc/bash.bashrc > /dev/null + echo 'UMASK 027' | sudo tee -a /etc/login.defs >/dev/null +fi +if sudo grep -qE '^[[:space:]]*#?[[:space:]]*umask' /etc/bash.bashrc; then + sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/bash.bashrc +else + echo 'umask 027' | sudo tee -a /etc/bash.bashrc >/dev/null fi if sudo grep -qE '^[[:space:]]*#?[[:space:]]*umask' /etc/profile; then - sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/profile + sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/profile else - echo 'umask 027' | sudo tee -a /etc/profile > /dev/null + echo 'umask 027' | sudo tee -a /etc/profile >/dev/null fi # [AUTH-9408] Logging of failed login attempts is enabled if sudo grep FAILLOG_ENAB /etc/login.defs; then - sudo sed -i 's/^FAILLOG_ENAB .*/FAILLOG_ENAB yes/' /etc/login.defs + sudo sed -i 's/^FAILLOG_ENAB .*/FAILLOG_ENAB yes/' /etc/login.defs else - echo 'FAILLOG_ENAB yes' | sudo tee -a /etc/login.defs > /dev/null + echo 'FAILLOG_ENAB yes' | sudo tee -a /etc/login.defs >/dev/null fi # [ACCT-9622] Enable process accounting @@ -353,21 +416,98 @@ sudo systemctl enable --now acct # [ACCT-9626] Enable sysstat to collect accounting data sudo pacman -S --noconfirm --needed sysstat -sudo systemctl enable --now sysstat-collect.timer sysstat-rotate.timer +sudo systemctl enable --now sysstat.service sysstat-collect.timer sysstat-rotate.timer # [ACCT-9628] Enable auditd to collect audit data sudo systemctl enable --now auditd audit-rules # [ACCT-9630] Configure auditd rules -sudo tee /etc/audit/rules.d/10-harden.rules > /dev/null </dev/null <=1000 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod +-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod +-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 +-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 + +-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 +-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 +-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 +-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 + +-a always,exit -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/chfn -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/expiry -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/fusermount3 -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/dotlockfile -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/lockfile -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/procmail -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/newgidmap -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/newuidmap -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/lib/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/lib/dbus-1.0/dbus-daemon-launch-helper -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/libexec/proxmox-mail-forward -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/libexec/pam-tmpdir/pam-tmpdir-helper -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/sbin/mount.cifs -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/sbin/mount.nfs -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged +-a always,exit -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged + +-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts +-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts + +-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete +-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete + +-w /etc/sudoers -p wa -k sudoers +-w /etc/sudoers.d/ -p wa -k sudoers + +-w /var/log/auth.log -p wa -k sudoaction + +-w /sbin/insmod -p x -k modules +-w /sbin/rmmod -p x -k modules +-w /sbin/modprobe -p x -k modules +-a always,exit -F arch=b64 -S init_module -S delete_module -k modules # Make the configuration immutable (must be the last line) -e 2 @@ -375,11 +515,11 @@ EOL # To test # Function to create basic systemd hardening drop-in -create_systemd_hardening () { - SERVICE="$1" - DROPIN="/etc/systemd/system/${SERVICE}.d" - sudo mkdir -p "$DROPIN" - sudo tee "$DROPIN/hardening.conf" > /dev/null </dev/null <&2 + echo "[$(date --rfc-3339=seconds)] $*" >&2 } log_warn() { - echo "[$(date --rfc-3339=seconds)] WARNING: $*" >&2 + echo "[$(date --rfc-3339=seconds)] WARNING: $*" >&2 } log_error() { - echo "[$(date --rfc-3339=seconds)] ERROR: $*" >&2 + echo "[$(date --rfc-3339=seconds)] ERROR: $*" >&2 } # Update system @@ -47,7 +47,7 @@ sudo apt-get install -y fail2ban # [STRG-1846] Disable drivers like firewire log "Disabling FireWire kernel modules..." -sudo tee /etc/modprobe.d/90-firewire-disable.conf > /dev/null </dev/null </dev/null 2>&1; then - sudo usbguard generate-policy | sudo tee /etc/usbguard/rules.conf > /dev/null - sudo sed -i 's/^PresentControllerPolicy=.*/PresentControllerPolicy=apply-policy/' /etc/usbguard/usbguard-daemon.conf || true - sudo systemctl enable --now usbguard + sudo usbguard generate-policy | sudo tee /etc/usbguard/rules.conf >/dev/null + sudo sed -i 's/^PresentControllerPolicy=.*/PresentControllerPolicy=apply-policy/' /etc/usbguard/usbguard-daemon.conf || true + sudo systemctl enable --now usbguard fi # [NETW-3032] Checking for ARP monitoring software @@ -77,7 +77,7 @@ sudo apt-get install -y arpon # [NETW-3200] Disable unused network protocols log "Disabling unused network protocol modules..." -sudo tee /etc/modprobe.d/90-network-protocols-disable.conf > /dev/null </dev/null < /dev/null </dev/null </dev/null; then echo read -s -p "Enter GRUB superuser password: " GRUB_PASS echo - GRUB_PASS_HASH=$(grub-mkpasswd-pbkdf2 <<< "$GRUB_PASS" | awk -F' ' '/PBKDF2 hash of your password is/ {print $7}') - sudo tee -a "$GRUB_PW_FILE" > /dev/null </dev/null < /dev/null <<'EOL' +sudo tee /etc/systemd/coredump.conf.d/99-disable-coredumps.conf >/dev/null <<'EOL' [Coredump] ProcessSizeMax=0 Storage=none @@ -194,21 +194,21 @@ EOL sudo systemctl daemon-reload || true sudo mkdir -p /etc/security/limits.d/ -sudo tee /etc/security/limits.d/20-disable-core-dumps.conf > /dev/null </dev/null </dev/null; then - echo '# Disable core dumps system-wide' | sudo tee -a /etc/profile > /dev/null - echo 'ulimit -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null - echo 'ulimit -S -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null - echo 'ulimit -H -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile > /dev/null + echo '# Disable core dumps system-wide' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -S -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null + echo 'ulimit -H -c 0 > /dev/null 2>&1' | sudo tee -a /etc/profile >/dev/null fi # [KRNL-6000] Sysctl settings for kernel hardening log "Applying sysctl hardened settings..." -sudo tee /etc/sysctl.d/99-hardened.conf > /dev/null <<'EOL' +sudo tee /etc/sysctl.d/99-hardened.conf >/dev/null <<'EOL' # Kernel and filesystem hardening settings kernel.randomize_va_space = 2 kernel.kptr_restrict = 2 @@ -251,9 +251,9 @@ sudo sysctl --system # [SHLL-6220] Idle session handling if ! grep -q 'TMOUT' /etc/profile 2>/dev/null; then - echo 'TMOUT=900' | sudo tee -a /etc/profile > /dev/null - echo 'readonly TMOUT' | sudo tee -a /etc/profile > /dev/null - echo 'export TMOUT' | sudo tee -a /etc/profile > /dev/null + echo 'TMOUT=900' | sudo tee -a /etc/profile >/dev/null + echo 'readonly TMOUT' | sudo tee -a /etc/profile >/dev/null + echo 'export TMOUT' | sudo tee -a /etc/profile >/dev/null fi # [MACF-6290] Enable MAC framework (AppArmor) @@ -264,10 +264,10 @@ sudo systemctl enable --now apparmor || true # [FILE-6344] Restricting process details to users via /proc mount options log "Configuring /proc to hide process info..." if ! grep -q '^proc\s\+/proc\s\+proc\s\+' /etc/fstab; then - echo '# /proc' | sudo tee -a /etc/fstab > /dev/null - echo 'proc /proc proc defaults,hidepid=2,gid=sudo 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /proc' | sudo tee -a /etc/fstab >/dev/null + echo 'proc /proc proc defaults,hidepid=2,gid=sudo 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^proc[[:space:]]\+/proc[[:space:]]\+proc[[:space:]]\+.*$|proc /proc proc defaults,hidepid=2,gid=sudo 0 0|' /etc/fstab + sudo sed -i 's|^proc[[:space:]]\+/proc[[:space:]]\+proc[[:space:]]\+.*$|proc /proc proc defaults,hidepid=2,gid=sudo 0 0|' /etc/fstab fi sudo systemctl daemon-reload sudo mount -o remount /proc @@ -276,8 +276,8 @@ sudo mount -o remount /proc log "Ensuring /dev, /dev/shm and /tmp have secure mount options..." if ! grep -q '^devtmpfs\s\+/dev\s\+devtmpfs\s\+' /etc/fstab; then - echo '# /dev' | sudo tee -a /etc/fstab > /dev/null - echo 'devtmpfs /dev devtmpfs rw,nosuid,noexec,relatime,size=10%,mode=755 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /dev' | sudo tee -a /etc/fstab >/dev/null + echo 'devtmpfs /dev devtmpfs rw,nosuid,noexec,relatime,size=10%,mode=755 0 0' | sudo tee -a /etc/fstab >/dev/null else sudo sed -i 's|^devtmpfs[[:space:]]\+/dev[[:space:]]\+devtmpfs[[:space:]]\+.*$|devtmpfs /dev devtmpfs rw,nosuid,noexec,relatime,size=10%,mode=755 0 0|' /etc/fstab fi @@ -285,26 +285,26 @@ sudo systemctl daemon-reload sudo mount -o remount /dev if ! grep -q '^tmpfs\s\+/dev/shm\s\+tmpfs\s\+' /etc/fstab; then - echo '# /dev/shm' | sudo tee -a /etc/fstab > /dev/null - echo 'tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /dev/shm' | sudo tee -a /etc/fstab >/dev/null + echo 'tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^tmpfs[[:space:]]\+/dev/shm[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab + sudo sed -i 's|^tmpfs[[:space:]]\+/dev/shm[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab fi sudo systemctl daemon-reload sudo mount -o remount /dev/shm if ! grep -q '^tmpfs\s\+/tmp\s\+tmpfs\s\+' /etc/fstab; then - echo '# /tmp' | sudo tee -a /etc/fstab > /dev/null - echo 'tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab > /dev/null + echo '# /tmp' | sudo tee -a /etc/fstab >/dev/null + echo 'tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0' | sudo tee -a /etc/fstab >/dev/null else - sudo sed -i 's|^tmpfs[[:space:]]\+/tmp[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab + sudo sed -i 's|^tmpfs[[:space:]]\+/tmp[[:space:]]\+tmpfs[[:space:]]\+.*$|tmpfs /tmp tmpfs rw,nosuid,nodev,noexec 0 0|' /etc/fstab fi sudo systemctl daemon-reload sudo mount -o remount /tmp # [FILE-6430] Disable mounting of some filesystems log "Disabling unnecessary filesystem modules..." -sudo tee /etc/modprobe.d/90-fs_blacklist.conf > /dev/null </dev/null < /dev/null </dev/null < /dev/null </dev/null < /dev/null <<'EOL' +sudo tee /etc/dpkg/dpkg.cfg.d/01-exclude-as >/dev/null <<'EOL' # Exclude as from being installed path-exclude /usr/bin/as path-exclude /usr/bin/x86_64-linux-gnu-as @@ -381,9 +381,9 @@ EOL # Correcting from chown->chmod to restrict access log "Restricting compiler binaries..." for bin in /usr/bin/as /usr/bin/x86_64-linux-gnu-as; do - if [ -f "$bin" ]; then - sudo chmod 700 "$bin" || true - fi + if [ -f "$bin" ]; then + sudo chmod 700 "$bin" || true + fi done # [PKGS-7320] Install package auditing tools @@ -392,23 +392,23 @@ sudo apt-get install -y debsecan || true # [PKGS-7370] Checking for debsums utility if ! dpkg -l | grep -q debsums; then - sudo apt-get install -y debsums || true + sudo apt-get install -y debsums || true fi # [SSH-7408] Check SSH specific defined options log "Checking SSH specific defined options..." set_sshd_option() { - local opt="$1" - local val="$2" - # If the option exists (possibly commented), replace the whole line; otherwise append - if sudo grep -Eq "^[[:space:]]*#?[[:space:]]*${opt}[[:space:]]+" /etc/ssh/sshd_config 2>/dev/null; then - sudo sed -ri "s|^[[:space:]]*#?[[:space:]]*${opt}[[:space:]]+.*|${opt} ${val}|" /etc/ssh/sshd_config - else - echo "${opt} ${val}" | sudo tee -a /etc/ssh/sshd_config > /dev/null - fi + local opt="$1" + local val="$2" + # If the option exists (possibly commented), replace the whole line; otherwise append + if sudo grep -Eq "^[[:space:]]*#?[[:space:]]*${opt}[[:space:]]+" /etc/ssh/sshd_config 2>/dev/null; then + sudo sed -ri "s|^[[:space:]]*#?[[:space:]]*${opt}[[:space:]]+.*|${opt} ${val}|" /etc/ssh/sshd_config + else + echo "${opt} ${val}" | sudo tee -a /etc/ssh/sshd_config >/dev/null + fi } -set_sshd_option "PermitRootLogin" "no" # Need to setup SSH key and local admin +set_sshd_option "PermitRootLogin" "no" # Need to setup SSH key and local admin set_sshd_option "PasswordAuthentication" "no" # Need to setup SSH key and local admin set_sshd_option "ChallengeResponseAuthentication" "no" set_sshd_option "AllowTcpForwarding" "no" @@ -426,7 +426,7 @@ sudo systemctl restart ssh || true log "Installing unattended-upgrades..." sudo apt-get install -y unattended-upgrades || true sudo dpkg-reconfigure -f noninteractive unattended-upgrades || true -sudo tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null <<'EOL' +sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null <<'EOL' APT::Periodic::Unattended-Upgrade "1"; EOL sudo systemctl enable --now unattended-upgrades || true @@ -452,7 +452,8 @@ sudo sed -i 's/^#SHA_CRYPT_MAX_ROUNDS .*/SHA_CRYPT_MAX_ROUNDS 5000000/' /etc/log sudo apt-get install -y libpam-pwquality || true set_pwq() { - local key="$1"; local val="$2" + local key="$1" + local val="$2" if sudo grep -Eq "^[[:space:]]*${key}[[:space:]]*=" /etc/security/pwquality.conf 2>/dev/null; then sudo sed -ri "s|^[[:space:]]*${key}[[:space:]]*=.*|${key} = ${val}|" /etc/security/pwquality.conf else @@ -473,7 +474,7 @@ set_pwq "enforcing" 1 # Add pam_pwquality to /etc/pam.d/common-password if not present if ! grep -q "pam_pwquality.so" /etc/pam.d/common-password 2>/dev/null; then - sudo sed -i "/pam_unix.so/ i password requisite pam_pwquality.so" /etc/pam.d/common-password || true + sudo sed -i "/pam_unix.so/ i password requisite pam_pwquality.so" /etc/pam.d/common-password || true fi # [AUTH-9286] Password aging @@ -484,24 +485,24 @@ sudo sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs || true if sudo grep -Eq '^[[:space:]]*#?[[:space:]]*UMASK\b' /etc/login.defs 2>/dev/null; then sudo sed -ri "s|^[[:space:]]*#?[[:space:]]*UMASK[[:space:]]+.*|UMASK 027|" /etc/login.defs || true else - echo 'UMASK 027' | sudo tee -a /etc/login.defs > /dev/null + echo 'UMASK 027' | sudo tee -a /etc/login.defs >/dev/null fi if grep -qE '^[[:space:]]*#?[[:space:]]*umask' /etc/bash.bashrc 2>/dev/null; then - sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/bash.bashrc || true + sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/bash.bashrc || true else - echo 'umask 027' | sudo tee -a /etc/bash.bashrc > /dev/null + echo 'umask 027' | sudo tee -a /etc/bash.bashrc >/dev/null fi if grep -qE '^[[:space:]]*#?[[:space:]]*umask' /etc/profile 2>/dev/null; then - sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/profile || true + sudo sed -i 's/^[[:space:]]*#\?[[:space:]]*umask.*/umask 027/' /etc/profile || true else - echo 'umask 027' | sudo tee -a /etc/profile > /dev/null + echo 'umask 027' | sudo tee -a /etc/profile >/dev/null fi # [AUTH-9408] Logging of failed login attempts is enabled if grep -q FAILLOG_ENAB /etc/login.defs 2>/dev/null; then - sudo sed -i 's/^FAILLOG_ENAB .*/FAILLOG_ENAB yes/' /etc/login.defs || true + sudo sed -i 's/^FAILLOG_ENAB .*/FAILLOG_ENAB yes/' /etc/login.defs || true else - echo 'FAILLOG_ENAB yes' | sudo tee -a /etc/login.defs > /dev/null + echo 'FAILLOG_ENAB yes' | sudo tee -a /etc/login.defs >/dev/null fi # [ACCT-9622] Enable process accounting @@ -535,7 +536,7 @@ if ! grep -q '^max_log_file_action[[:space:]]*=[[:space:]]*keep_logs' /etc/audit fi # [ACCT-9630] Configure auditd rules -sudo tee /etc/audit/rules.d/10-harden.rules > /dev/null </dev/null <