Improved debian hardening
This commit is contained in:
@@ -3,7 +3,6 @@ set -euo pipefail
|
||||
|
||||
# Debian Hardening Script
|
||||
# Adapted from the Arch Linux hardening script (arch-hardening.sh)
|
||||
# Run as root or via sudo
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -22,11 +21,33 @@ log_error() {
|
||||
# Update system
|
||||
log "Updating packages..."
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade -y
|
||||
sudo apt-get dist-upgrade -y
|
||||
|
||||
# [DEB-0280] Ensure libpam-tmpdir is installed and enabled
|
||||
sudo apt-get install -y libpam-tmpdir
|
||||
if ! grep -q "pam_tmpdir.so" /etc/pam.d/common-session 2>/dev/null; then
|
||||
sudo sed -i "/pam_unix.so/ a session optional pam_tmpdir.so" /etc/pam.d/common-session || true
|
||||
fi
|
||||
|
||||
# [DEB-0810] Ensure apt-listbugs is installed
|
||||
log "Installing apt-listbugs..."
|
||||
sudo apt-get install -y apt-listbugs
|
||||
|
||||
# [DEB-0811] Ensure apt-listchanges is installed
|
||||
log "Installing apt-listchanges..."
|
||||
sudo apt-get install -y apt-listchanges
|
||||
|
||||
# [DEB-0831] Ensure needrestart is installed
|
||||
log "Installing needrestart..."
|
||||
sudo apt-get install -y needrestart
|
||||
|
||||
# [DEB-0880] Ensure fail2ban is installed
|
||||
log "Installing fail2ban..."
|
||||
sudo apt-get install -y fail2ban
|
||||
|
||||
# [STRG-1846] Disable drivers like firewire
|
||||
log "Disabling FireWire kernel modules..."
|
||||
sudo tee /etc/modprobe.d/firewire-disable.conf > /dev/null <<EOL
|
||||
sudo tee /etc/modprobe.d/90-firewire-disable.conf > /dev/null <<EOL
|
||||
# Disable FireWire kernel modules to prevent unauthorized DMA access
|
||||
blacklist firewire-core
|
||||
install firewire-core /bin/false
|
||||
@@ -37,19 +58,10 @@ install firewire-sbp2 /bin/false
|
||||
EOL
|
||||
|
||||
# [LOGG-2154] Ensure system log is configured to send logs to a remote log server
|
||||
# Debian uses rsyslog by default; install rsyslog to match standard Debian setups
|
||||
log "Installing rsyslog..."
|
||||
sudo apt-get install -y rsyslog
|
||||
sudo systemctl enable --now rsyslog
|
||||
|
||||
# [NETW-2706] Ensure DNSSEC validation is enabled (systemd-resolved)
|
||||
log "Enabling DNSSEC in systemd-resolved..."
|
||||
if [ -f /etc/systemd/resolved.conf ]; then
|
||||
sudo sed -i '/^DNSSEC=/d' /etc/systemd/resolved.conf || true
|
||||
echo 'DNSSEC=yes' | sudo tee -a /etc/systemd/resolved.conf > /dev/null
|
||||
sudo systemctl restart systemd-resolved
|
||||
fi
|
||||
|
||||
# [USB-3000] Ensure USBGUARD is installed and configured
|
||||
log "Installing usbguard..."
|
||||
sudo apt-get install -y usbguard
|
||||
@@ -59,19 +71,13 @@ if command -v usbguard >/dev/null 2>&1; then
|
||||
sudo systemctl enable --now usbguard
|
||||
fi
|
||||
|
||||
# [NETW-3032] Ensure arpwatch is installed and enabled
|
||||
log "Installing arpwatch..."
|
||||
sudo apt-get install -y arpwatch
|
||||
iface=$(ip -o link show | awk -F': ' '{print $2}' | sed 's/@.*$//' | grep -Ev '^(lo|virbr|vmbr)' | head -n1 || true)
|
||||
if [ -n "$iface" ]; then
|
||||
sudo systemctl enable --now "arpwatch@${iface}.service" || true
|
||||
else
|
||||
log_warn "No suitable network interface found for arpwatch; service not enabled."
|
||||
fi
|
||||
# [NETW-3032] Checking for ARP monitoring software
|
||||
log "Installing Arpon..."
|
||||
sudo apt-get install -y arpon
|
||||
|
||||
# [NETW-3200] Disable unused network protocols
|
||||
log "Disabling unused network protocol modules..."
|
||||
sudo tee /etc/modprobe.d/network-protocols-disable.conf > /dev/null <<EOL
|
||||
sudo tee /etc/modprobe.d/90-network-protocols-disable.conf > /dev/null <<EOL
|
||||
# Disable unnecessary network protocols to reduce attack surface
|
||||
blacklist dccp
|
||||
install dccp /bin/false
|
||||
@@ -86,49 +92,96 @@ blacklist tipc
|
||||
install tipc /bin/false
|
||||
EOL
|
||||
|
||||
# [MALW-3276] Ensure rkhunter is installed
|
||||
log "Installing rkhunter..."
|
||||
sudo apt-get install -y rkhunter
|
||||
sudo rkhunter --propupd || true
|
||||
# Add common whitelists
|
||||
sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/egrep" /etc/rkhunter.conf || true
|
||||
sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/fgrep" /etc/rkhunter.conf || true
|
||||
sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/ldd" /etc/rkhunter.conf || true
|
||||
sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/rkhunter" /etc/rkhunter.conf || true
|
||||
# [MALW-3276] Install rkhunter and update properties
|
||||
# log "Installing and configuring rkhunter (MALW-3276)..."
|
||||
# sudo apt-get install -y rkhunter || true
|
||||
# if command -v rkhunter >/dev/null 2>&1; then
|
||||
# sudo rkhunter --update || true
|
||||
# sudo rkhunter --propupd || true
|
||||
# # Add common whitelists (reduce false positives)
|
||||
# sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/egrep" /etc/rkhunter.conf || true
|
||||
# sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/fgrep" /etc/rkhunter.conf || true
|
||||
# sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/ldd" /etc/rkhunter.conf || true
|
||||
# sudo sed -i "$ a SCRIPTWHITELIST=/usr/bin/rkhunter" /etc/rkhunter.conf || true
|
||||
# fi
|
||||
|
||||
# [MALW-3282] Ensure ClamAV is installed
|
||||
log "Installing ClamAV..."
|
||||
sudo apt-get install -y clamav clamav-freshclam
|
||||
sudo freshclam || true
|
||||
sudo systemctl enable --now clamav-freshclam || true
|
||||
sleep 2
|
||||
sudo systemctl enable --now clamav-daemon || true
|
||||
# [MALW-3282] Check for clamscan
|
||||
# log "Checking for ClamAV installation..."
|
||||
# if ! command -v clamscan >/dev/null 2>&1; then
|
||||
# log "Installing ClamAV..."
|
||||
# sudo apt-get install -y clamdscan
|
||||
# sudo freshclam || true
|
||||
# else
|
||||
# log "Clamscan is already installed."
|
||||
# fi
|
||||
|
||||
# [MALW-3284] Check for clamd
|
||||
# log "Checking for clamd..."
|
||||
# if ! command -v clamd >/dev/null 2>&1; then
|
||||
# log "Installing clamd..."
|
||||
# sudo apt-get install -y clamav clamav-daemon
|
||||
# sudo systemctl enable --now clamav-daemon || true
|
||||
# else
|
||||
# log "Clamd is already installed."
|
||||
# fi
|
||||
|
||||
# [FINT-4350] Install a file integrity tool
|
||||
log "Installing AIDE..."
|
||||
sudo apt-get install -y aide
|
||||
sudo aide --init || true
|
||||
if [ -f /var/lib/aide/aide.db.new.gz ]; then
|
||||
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz || true
|
||||
fi
|
||||
sudo systemctl enable --now aidecheck.timer || true
|
||||
|
||||
# [FIRE-45XX] Firewall configuration: ensure nftables is installed and iptables removed if present
|
||||
log "Installing nftables and removing iptables (if installed)..."
|
||||
if dpkg -s iptables >/dev/null 2>&1; then
|
||||
sudo apt-get remove -y iptables || true
|
||||
fi
|
||||
sudo apt-get install -y nftables
|
||||
|
||||
sudo tee /etc/modprobe.d/ip_tables-disable.conf > /dev/null <<EOL
|
||||
log "Disabling iptables to prevent conflicts with nftables (default on debian since Buster)..."
|
||||
sudo tee /etc/modprobe.d/90-ip_tables-disable.conf > /dev/null <<EOL
|
||||
# Disable ip_tables to prevent conflicts with nftables
|
||||
blacklist ip_tables
|
||||
install ip_tables /bin/false
|
||||
EOL
|
||||
|
||||
# [TOOL-5190] Ensure IDS/IPS tools are installed (snort)
|
||||
log "Installing snort..."
|
||||
sudo apt-get install -y snort
|
||||
sudo systemctl enable --now snort || true
|
||||
# [BOOT-5122] Check for GRUB boot password
|
||||
log "Setting GRUB boot password..."
|
||||
GRUB_PW_FILE="/etc/grub.d/40_custom"
|
||||
if ! grep -q "set superusers=" "$GRUB_PW_FILE" 2>/dev/null; then
|
||||
read -s -p "Enter GRUB superuser name: " GRUB_USER
|
||||
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 <<EOL
|
||||
set superusers="$GRUB_USER"
|
||||
password_pbkdf2 $GRUB_USER $GRUB_PASS_HASH
|
||||
EOL
|
||||
sudo update-grub || true
|
||||
else
|
||||
log "GRUB superuser already configured; skipping."
|
||||
fi
|
||||
|
||||
# Fix ^GRUB_CMDLINE_LINUX=.*audit=1 is not present in /etc/default/grub
|
||||
if ! grep -q 'audit=1' /etc/default/grub 2>/dev/null; then
|
||||
log "Enabling audit=1 in GRUB_CMDLINE_LINUX..."
|
||||
sudo sed -i 's|^GRUB_CMDLINE_LINUX="\(.*\)"|GRUB_CMDLINE_LINUX="\1 audit=1"|' /etc/default/grub
|
||||
sudo update-grub || true
|
||||
else
|
||||
log "audit=1 already present in GRUB_CMDLINE_LINUX; skipping."
|
||||
fi
|
||||
|
||||
# ^GRUB_CMDLINE_LINUX=.*audit_backlog_limit=8192 is not present in /etc/default/grub
|
||||
if ! grep -q 'audit_backlog_limit=8192' /etc/default/grub 2>/dev/null; then
|
||||
log "Enabling audit_backlog_limit=8192 in GRUB_CMDLINE_LINUX..."
|
||||
sudo sed -i 's|^GRUB_CMDLINE_LINUX="\(.*\)"|GRUB_CMDLINE_LINUX="\1 audit_backlog_limit=8192"|' /etc/default/grub
|
||||
sudo update-grub || true
|
||||
else
|
||||
log "audit_backlog_limit=8192 already present in GRUB_CMDLINE_LINUX; skipping."
|
||||
fi
|
||||
|
||||
# [TOOL-5190] Ensure IDS/IPS tools are installed (suricata)
|
||||
# log "Installing suricata..."
|
||||
# sudo apt-get install -y suricata
|
||||
# sudo systemctl enable --now suricata || true
|
||||
|
||||
# [KRNL-5820] Disable core dumps
|
||||
log "Disabling core dumps via systemd and limits..."
|
||||
@@ -177,14 +230,22 @@ 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
|
||||
|
||||
@@ -195,24 +256,34 @@ if ! grep -q 'TMOUT' /etc/profile 2>/dev/null; then
|
||||
echo 'export TMOUT' | sudo tee -a /etc/profile > /dev/null
|
||||
fi
|
||||
|
||||
# [MACF-6290] Enable AppArmor
|
||||
log "Installing and enabling AppArmor..."
|
||||
sudo apt-get install -y apparmor apparmor-utils
|
||||
# [MACF-6290] Enable MAC framework (AppArmor)
|
||||
log "Enabling AppArmor..."
|
||||
sudo apt-get install -y apparmor apparmor-utils || true
|
||||
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=wheel 0 0' | 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=1,gid=wheel 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
|
||||
|
||||
# [FILE-6374] Check /dev/shm and /tmp mount options
|
||||
log "Ensuring /dev/shm and /tmp have secure mount options..."
|
||||
# [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|^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
|
||||
@@ -233,11 +304,14 @@ sudo mount -o remount /tmp
|
||||
|
||||
# [FILE-6430] Disable mounting of some filesystems
|
||||
log "Disabling unnecessary filesystem modules..."
|
||||
sudo tee /etc/modprobe.d/fs_blacklist.conf > /dev/null <<EOL
|
||||
sudo tee /etc/modprobe.d/90-fs_blacklist.conf > /dev/null <<EOL
|
||||
# Blacklist unnecessary filesystem modules to reduce attack surface
|
||||
blacklist cramfs
|
||||
install cramfs /bin/false
|
||||
|
||||
blacklist freevxfs
|
||||
install freevxfs /bin/false
|
||||
|
||||
blacklist hfs
|
||||
install hfs /bin/false
|
||||
|
||||
@@ -256,6 +330,7 @@ EOL
|
||||
|
||||
# [BANN-7126] Add legal banner to /etc/issue
|
||||
log "Adding legal banner to /etc/issue..."
|
||||
sudo systemctl disable --now pvebanner || true
|
||||
sudo tee /etc/issue > /dev/null <<EOL
|
||||
********************************************************************
|
||||
* WARNING - UNAUTHORIZED ACCESS *
|
||||
@@ -272,41 +347,102 @@ sudo tee /etc/issue > /dev/null <<EOL
|
||||
\n - \l
|
||||
EOL
|
||||
|
||||
# [BANN-7130] Check issue.net banner file contents
|
||||
log "Checking /etc/issue.net banner file contents..."
|
||||
if ! sudo grep -q "WARNING - UNAUTHORIZED ACCESS" /etc/issue.net; then
|
||||
log "Adding legal banner to /etc/issue.net..."
|
||||
sudo tee /etc/issue.net > /dev/null <<EOL
|
||||
********************************************************************
|
||||
* WARNING - UNAUTHORIZED ACCESS *
|
||||
* *
|
||||
* Unauthorized access to this computer system is strictly *
|
||||
* prohibited. Individuals accessing, using, or modifying this *
|
||||
* system without explicit authorization will be subject to legal *
|
||||
* action and prosecuted to the fullest extent of the law. *
|
||||
* *
|
||||
* Authorized users should have no expectation of privacy. All *
|
||||
* activity on this system is monitored, recorded, and may be used *
|
||||
* as evidence in criminal or civil proceedings. *
|
||||
********************************************************************
|
||||
\n - \l
|
||||
EOL
|
||||
fi
|
||||
|
||||
# [HRDN-7220] Check if one or more compilers are installed
|
||||
# Disallow apt to extract /usr/bin/as by making a dpkg config
|
||||
log "Checking if as is present and excluding it from installation..."
|
||||
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
|
||||
EOL
|
||||
|
||||
# [HRDN-7222] Restricting compiler access to root user only
|
||||
# Correcting from chown->chmod to restrict access
|
||||
log "Restricting compiler binaries..."
|
||||
for bin in /usr/bin/as /usr/bin/gcc /usr/bin/g++ /usr/bin/cc /usr/bin/c++ /usr/bin/ld /usr/bin/lld /usr/bin/clang; do
|
||||
for bin in /usr/bin/as /usr/bin/x86_64-linux-gnu-as; do
|
||||
if [ -f "$bin" ]; then
|
||||
sudo chmod 700 "$bin" || true
|
||||
fi
|
||||
done
|
||||
|
||||
# [PKGS-7320] Install package auditing tools
|
||||
log "Installing arch-audit equivalent packages..."
|
||||
# Debian doesn't have arch-audit; install debsecan for security audits
|
||||
log "Installing package auditing..."
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
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"
|
||||
set_sshd_option "AllowAgentForwarding" "no"
|
||||
set_sshd_option "X11Forwarding" "no"
|
||||
set_sshd_option "TCPKeepAlive" "no"
|
||||
set_sshd_option "ClientAliveCountMax" "2"
|
||||
set_sshd_option "MaxAuthTries" "3"
|
||||
set_sshd_option "MaxSessions" "2"
|
||||
set_sshd_option "LogLevel" "VERBOSE"
|
||||
|
||||
sudo systemctl restart ssh || true
|
||||
|
||||
# [PKGS-7420] Detect toolkit to automatically download and apply upgrades
|
||||
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'
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
EOL
|
||||
sudo systemctl enable --now unattended-upgrades || true
|
||||
|
||||
# [FILE-7524] Ensuring file permissions
|
||||
log "Enforcing file permissions for SSH & cron..."
|
||||
sudo chmod -R 640 /var/log/ || true
|
||||
sudo chmod 600 /etc/crontab || true
|
||||
sudo chmod 700 /etc/cron.* || true
|
||||
sudo chmod -R 700 /etc/cron.d/ || true
|
||||
sudo chmod 600 /etc/ssh/sshd_config || true
|
||||
sudo chmod 700 /etc/cron.hourly || true
|
||||
|
||||
# [CRYP-8004] Presence of hardware RNG and software PRNG
|
||||
log "Installing rng-tools and haveged..."
|
||||
sudo apt-get install -y rng-tools haveged || true
|
||||
sudo systemctl enable --now rng-tools haveged || true
|
||||
|
||||
# [CRYP-8006] Ensure MemoryOverwriteRequest-bit set (UEFI) using system-shutdown script
|
||||
sudo tee /usr/lib/systemd/system-shutdown/mor-bit-wipe.sh > /dev/null <<'EOL'
|
||||
#!/bin/bash
|
||||
MOR_VAR_PATH="/sys/firmware/efi/efivars/MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829"
|
||||
if [ -e "$MOR_VAR_PATH" ]; then
|
||||
printf "\x07\x00\x00\x00\x01" | dd of="$MOR_VAR_PATH" bs=5 count=1 conv=notrunc >/dev/null 2>&1 || true
|
||||
echo "$(date) - Successfully set MOR-bit for next boot memory wipe." >> /var/log/mor-wipe.log || true
|
||||
fi
|
||||
exit 0
|
||||
EOL
|
||||
sudo chmod +x /usr/lib/systemd/system-shutdown/mor-bit-wipe.sh || true
|
||||
# [CRYP-8004] Presence of hardware RNG tools
|
||||
log "Installing rng-tools..."
|
||||
sudo apt-get install -y rng-tools-debian || true
|
||||
sudo systemctl enable --now rng-tools-debian || true
|
||||
|
||||
# [AUTH-*] Password and PAM related settings
|
||||
log "Configuring password hashing and pam pwquality..."
|
||||
@@ -315,37 +451,50 @@ sudo sed -i 's/^#SHA_CRYPT_MIN_ROUNDS .*/SHA_CRYPT_MIN_ROUNDS 5000/' /etc/login.
|
||||
sudo sed -i 's/^#SHA_CRYPT_MAX_ROUNDS .*/SHA_CRYPT_MAX_ROUNDS 5000000/' /etc/login.defs || true
|
||||
|
||||
sudo apt-get install -y libpam-pwquality || true
|
||||
sudo tee /etc/security/pwquality.conf > /dev/null <<EOL
|
||||
# PAM pwquality configuration file
|
||||
retry = 3
|
||||
difok = 6
|
||||
minlen = 14
|
||||
dcredit = -1
|
||||
ucredit = -1
|
||||
ocredit = -1
|
||||
lcredit = -1
|
||||
EOL
|
||||
set_pwq() {
|
||||
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
|
||||
sudo sh -c "printf '%s = %s\n' '${key}' '${val}' >> /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
|
||||
|
||||
# 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 retry=3" /etc/pam.d/common-password || true
|
||||
fi
|
||||
|
||||
# [AUTH-9286] Password change days
|
||||
# [AUTH-9286] Password aging
|
||||
sudo sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 7/' /etc/login.defs || true
|
||||
sudo sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs || true
|
||||
|
||||
# [AUTH-9328] Default umask
|
||||
sudo sed -i 's/^UMASK.*/UMASK 027/' /etc/login.defs || true
|
||||
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
|
||||
if sudo grep -Eq '^[[:space:]]*#?[[:space:]]*UMASK\b' /etc/login.defs 2>/dev/null; then
|
||||
sudo sed -ri "s|^[[:space:]]*#?[[:space:]]*UMASK[[:space:]]+.*|UMASK 077|" /etc/login.defs || true
|
||||
else
|
||||
echo 'umask 027' | sudo tee -a /etc/bash.bashrc > /dev/null
|
||||
echo 'UMASK 077' | 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 077/' /etc/bash.bashrc || true
|
||||
else
|
||||
echo 'umask 077' | 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 077/' /etc/profile || true
|
||||
else
|
||||
echo 'umask 027' | sudo tee -a /etc/profile > /dev/null
|
||||
echo 'umask 077' | sudo tee -a /etc/profile > /dev/null
|
||||
fi
|
||||
|
||||
# [AUTH-9408] Logging of failed login attempts is enabled
|
||||
@@ -367,21 +516,130 @@ sudo systemctl enable --now sysstat || true
|
||||
sudo apt-get install -y auditd || true
|
||||
sudo systemctl enable --now auditd || true
|
||||
|
||||
# Fix ^space_left_action[[:space:]]*=[[:space:]]*email is not present in /etc/audit/auditd.conf
|
||||
if ! grep -q '^space_left_action[[:space:]]*=[[:space:]]*email' /etc/audit/auditd.conf 2>/dev/null; then
|
||||
log "Configuring auditd to email on low disk space..."
|
||||
sudo sed -i 's/^space_left_action[[:space:]]*=.*/space_left_action = email/' /etc/audit/auditd.conf || true
|
||||
# Set admin email for auditd notifications
|
||||
ADMIN_EMAIL="root@localhost" # Change as needed
|
||||
if grep -q '^admin_space_left_email[[:space:]]*=' /etc/audit/auditd.conf 2>/dev/null; then
|
||||
sudo sed -i "s|^admin_space_left_email[[:space:]]*=.*|admin_space_left_email = ${ADMIN_EMAIL}|" /etc/audit/auditd.conf || true
|
||||
else
|
||||
echo "admin_space_left_email = ${ADMIN_EMAIL}" | sudo tee -a /etc/audit/auditd.conf > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fix ^admin_space_left_action[[:space:]]*=[[:space:]]*halt is not present in /etc/audit/auditd.conf
|
||||
if ! grep -q '^admin_space_left_action[[:space:]]*=[[:space:]]*halt' /etc/audit/auditd.conf 2>/dev/null; then
|
||||
log "Configuring auditd to halt on critical disk space..."
|
||||
sudo sed -i 's/^admin_space_left_action[[:space:]]*=.*/admin_space_left_action = halt/' /etc/audit/auditd.conf || true
|
||||
fi
|
||||
|
||||
# Fix ^max_log_file_action[[:space:]]*=[[:space:]]*keep_logs is not present in /etc/audit/auditd.conf
|
||||
if ! grep -q '^max_log_file_action[[:space:]]*=[[:space:]]*keep_logs' /etc/audit/auditd.conf 2>/dev/null; then
|
||||
log "Configuring auditd to keep logs on max log file size..."
|
||||
sudo sed -i 's/^max_log_file_action[[:space:]]*=.*/max_log_file_action = keep_logs/' /etc/audit/auditd.conf || true
|
||||
fi
|
||||
|
||||
# [ACCT-9630] Configure auditd rules
|
||||
sudo tee /etc/audit/rules.d/10-harden.rules > /dev/null <<EOL
|
||||
# Monitor attempts to change system time
|
||||
-w /etc/localtime -p wa -k time-change
|
||||
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
|
||||
-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change
|
||||
-a always,exit -F arch=b64 -S clock_settime -k time-change
|
||||
-a always,exit -F arch=b32 -S clock_settime -k time-change
|
||||
|
||||
# Monitor attempts to change user/group info
|
||||
-w /etc/passwd -p wa -k user-info
|
||||
-w /etc/shadow -p wa -k user-info
|
||||
-w /etc/group -p wa -k user-info
|
||||
-w /etc/gshadow -p wa -k user-info
|
||||
-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
|
||||
|
||||
-a exit,always -F arch=b64 -S sethostname -S setdomainname -k system-locale
|
||||
-a exit,always -F arch=b32 -S sethostname -S 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/network -p wa -k system-locale
|
||||
|
||||
-w /etc/apparmor/ -p wa -k MAC-policy
|
||||
-w /etc/apparmor.d/ -p wa -k MAC-policy
|
||||
|
||||
-w /var/log/faillog -p wa -k logins
|
||||
-w /var/log/lastlog -p wa -k logins
|
||||
-w /var/log/tallylog -p wa -k logins
|
||||
|
||||
-w /var/run/utmp -p wa -k session
|
||||
-w /var/log/wtmp -p wa -k session
|
||||
-w /var/log/btmp -p wa -k session
|
||||
|
||||
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=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
|
||||
EOL
|
||||
|
||||
# Fix ^Storage=persistent is not present in /etc/systemd/journald.conf
|
||||
if ! grep -q '^Storage=persistent' /etc/systemd/journald.conf 2>/dev/null; then
|
||||
log "Configuring journald to use persistent storage..."
|
||||
sudo sed -i 's/^#Storage=.*/Storage=persistent/' /etc/systemd/journald.conf || true
|
||||
sudo systemctl restart systemd-journald || true
|
||||
fi
|
||||
|
||||
log "Debian hardening completed. Review the log above for applied steps and check for any package/service variations on your system."
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user