.. ============================================================ .. Unit 4: System Hardening .. Apply System Hardening Techniques to Reduce Attack Surfaces .. ============================================================ ======================================================== Unit 4: System Hardening — Reducing Attack Surfaces ======================================================== Introduction ============ Every computing system, from a single workstation to a sprawling enterprise network, begins its life in a default state that prioritises compatibility and ease-of-use over security. Manufacturers and vendors ship operating systems with numerous services running, ports open, accounts active, and features enabled — most of which the average deployment will never require. Each of these unnecessary components is a potential foothold for an attacker. **System hardening** is the disciplined process of eliminating that excess: disabling unneeded services, enforcing strong authentication, applying security patches, restricting permissions, configuring audit logging, and tuning the operating system itself to resist exploitation. The goal is to shrink the **attack surface** — the sum of all points where an unauthorised user could attempt to interact with or compromise the system — to the smallest practical footprint. This chapter covers the principles, methodologies, and practical techniques of system hardening across common platforms. By the end you will be able to assess a system's current posture, apply baseline hardening controls, verify your work, and understand how hardening fits into the broader security lifecycle. .. note:: All command examples in this chapter target **Linux (Ubuntu/RHEL family)** and **Windows Server 2019/2022** unless otherwise stated. Equivalent concepts apply to macOS, BSD, and cloud-native environments. ---- Core Concepts ============= The Attack Surface ------------------ The attack surface of a system comprises every avenue through which a threat actor might gain unauthorised access, escalate privilege, or cause damage. It can be categorised into three dimensions: .. list-table:: Attack Surface Dimensions :header-rows: 1 :widths: 20 40 40 * - Dimension - Examples - Hardening Response * - **Network** - Open TCP/UDP ports, running services, network protocols - Firewall rules, disabling services, protocol restrictions * - **Software** - Installed applications, libraries, OS components, unpatched CVEs - Patch management, software removal, application allow-listing * - **Human / Configuration** - Default credentials, excessive permissions, misconfigured policies - Password policies, least privilege, configuration baselines The Principle of Least Privilege --------------------------------- The single most important principle in system hardening is **least privilege**: every user, process, and service should operate with the minimum set of permissions required to perform its legitimate function — nothing more. Violations of least privilege compound over time. A service account granted local administrator rights for convenience, a developer left in the Domain Admins group after a project ends, a web server process that can write to ``/etc`` — each represents an opportunity for an attacker who compromises that identity to escalate impact dramatically. .. rubric:: Example — Over-Privileged Web Application A web application runs as ``root`` on a Linux server. An attacker exploits a Remote Code Execution (RCE) vulnerability in a third-party library. Because the process runs as root they immediately have full system control: they can read ``/etc/shadow``, install a rootkit, pivot to other hosts, and exfiltrate data. Had the application run as a dedicated low-privilege account (e.g., ``www-data``) confined to ``/var/www``, the attacker's foothold would be severely restricted. They could not read sensitive system files, could not write to system directories, and privilege escalation would require an additional exploit. Defence in Depth ----------------- No single control is infallible. Hardening is one layer in a **defence-in- depth** strategy: a security architecture where multiple overlapping controls ensure that the failure of any one layer does not result in total compromise. :: ┌─────────────────────────────────────────────────┐ │ Perimeter │ ← Firewalls, IDS/IPS │ ┌───────────────────────────────────────────┐ │ │ │ Network Segment │ │ ← VLANs, ACLs │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ Host Hardening │ │ │ ← This chapter │ │ │ ┌───────────────────────────────┐ │ │ │ │ │ │ │ Application Security │ │ │ │ ← Input validation, WAF │ │ │ │ ┌───────────────────────┐ │ │ │ │ │ │ │ │ │ Data Layer │ │ │ │ │ ← Encryption, DLP │ │ │ │ └───────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────────┘ │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘ Hardening Benchmarks and Standards ------------------------------------ Rather than reinventing controls for every deployment, practitioners leverage established hardening benchmarks: **CIS Benchmarks** The Center for Internet Security publishes detailed, community-reviewed configuration guides for virtually every major OS, application, and cloud platform. Each benchmark item is categorised as Level 1 (essential, minimal operational impact) or Level 2 (defence-in-depth, may impact usability). **DISA STIGs** The Defense Information Systems Agency Security Technical Implementation Guides are mandatory within the US Department of Defense and widely adopted in government and regulated industries. STIGs are more prescriptive and generally stricter than CIS benchmarks. **NIST SP 800-123** NIST's *Guide to General Server Security* provides vendor-neutral hardening principles applicable to any platform. **Vendor Security Guides** Microsoft Secure Baselines (via Microsoft Security Compliance Toolkit), Red Hat Security Guide, and Apple Platform Security are platform-specific references that complement the above. ---- Patch Management ================ Why Patching Is Hardening -------------------------- Unpatched vulnerabilities are the leading cause of successful breaches. Applying security patches is arguably the single highest-ROI hardening activity because it directly eliminates known, exploited weaknesses rather than merely raising the bar for attackers. Patch management encompasses: 1. **Inventory** — knowing what software and versions are installed 2. **Monitoring** — tracking vendor advisories and CVE databases 3. **Testing** — validating patches in a non-production environment 4. **Deployment** — applying patches within defined SLA windows 5. **Verification** — confirming patches are applied and systems are compliant Patch SLA Tiers --------------- Risk-based patch SLAs allow organisations to prioritise effort proportional to severity: .. list-table:: Common Patch SLA Framework :header-rows: 1 :widths: 20 20 20 40 * - CVSS Score - Severity - Target Remediation - Notes * - 9.0 – 10.0 - Critical - 24 – 72 hours - Particularly if public exploit exists (CISA KEV) * - 7.0 – 8.9 - High - 7 – 14 days - Expedite if actively exploited * - 4.0 – 6.9 - Medium - 30 days - Standard patch cycle * - 0.1 – 3.9 - Low - 90 days / next major cycle - Bundle with routine maintenance Linux Patch Management ----------------------- .. code-block:: bash # Ubuntu / Debian — update package lists and apply security patches sudo apt update sudo apt upgrade --only-upgrade # upgrade all installed packages sudo apt-get dist-upgrade # also handles dependency changes # Apply ONLY security updates (Ubuntu) sudo unattended-upgrades --dry-run # preview sudo unattended-upgrades # apply # RHEL / CentOS Stream / Rocky Linux sudo dnf check-update sudo dnf update --security # security updates only sudo dnf update # all updates # Check which packages have available security updates sudo dnf updateinfo list security # Identify packages with known CVEs (requires subscription on RHEL) sudo dnf updateinfo list cves Configuring Automatic Security Updates (Ubuntu) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash # Install unattended-upgrades sudo apt install unattended-upgrades # Edit /etc/apt/apt.conf.d/50unattended-upgrades # Ensure this origin is uncommented: # "${distro_id}:${distro_codename}-security"; # Configure update schedule in /etc/apt/apt.conf.d/20auto-upgrades: APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::AutocleanInterval "7"; Windows Patch Management ------------------------- .. code-block:: powershell # Check for missing updates via PSWindowsUpdate module Install-Module PSWindowsUpdate -Force Get-WindowsUpdate # Install all available security updates Install-WindowsUpdate -Category "Security Updates" -AcceptAll -AutoReboot # WSUS integration — set update server via registry Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` -Name "UseWUServer" -Value 1 # Query installed hotfixes Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 20 # Check for updates using Windows Update API (no module required) $UpdateSession = New-Object -ComObject Microsoft.Update.Session $UpdateSearcher = $UpdateSession.CreateUpdateSearcher() $SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'") $SearchResult.Updates | Select-Object Title, MsrcSeverity .. warning:: Always test patches in a representative staging environment before deploying to production. While rare, patches can introduce regressions. Maintain a documented rollback procedure for critical systems. ---- Service and Port Management ============================ Identifying Running Services ----------------------------- The first step in service hardening is a complete inventory of what is running and why. Every service listening on a network port is a potential attack vector. .. code-block:: bash # Linux — list all listening ports and associated processes sudo ss -tlnp # TCP listening, numeric, show process sudo ss -ulnp # UDP listening sudo netstat -tlnp # alternative (deprecated but widely available) # List all running services (systemd) systemctl list-units --type=service --state=running # List ALL installed services (running and stopped) systemctl list-unit-files --type=service # Check if a specific service is enabled at boot systemctl is-enabled bluetooth .. code-block:: powershell # Windows — list listening ports with process IDs netstat -ano | Where-Object { $_ -match "LISTENING" } # Map ports to process names Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, @{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).Name}} # List all services Get-Service | Sort-Object Status -Descending # List services set to start automatically Get-Service | Where-Object { $_.StartType -eq "Automatic" } Disabling Unnecessary Services -------------------------------- Once you have an inventory, disable everything not required by the system's documented purpose. Apply the principle: **if in doubt, disable**. .. rubric:: Common Services to Evaluate for Disabling .. list-table:: :header-rows: 1 :widths: 30 35 35 * - Service - Platform - Risk if Unnecessary * - Telnet - Linux/Windows - Plaintext credentials, deprecated by SSH * - FTP (vsftpd, IIS FTP) - Linux/Windows - Plaintext credentials; use SFTP/FTPS * - SNMP v1/v2 - Both - Community string brute-force, information disclosure * - Remote Registry - Windows - Remote registry access by attackers * - Print Spooler - Windows - PrintNightmare (CVE-2021-1675) and related exploits * - Bluetooth - Both - BLUEBORNE and proximity attacks on servers * - NFS (without auth) - Linux - Unauthenticated file system access * - X11 forwarding - Linux - GUI exposure; rarely needed on servers * - Avahi/mDNS - Linux - Network discovery; unnecessary on servers .. code-block:: bash # Linux — disable and stop a service immediately sudo systemctl stop bluetooth sudo systemctl disable bluetooth sudo systemctl mask bluetooth # prevent re-enabling even by other services # Verify it will not start at boot sudo systemctl is-enabled bluetooth # should output "masked" # Remove a package entirely (Ubuntu example) sudo apt purge telnet xinetd rsh-server nis yp-tools sudo apt autoremove .. code-block:: powershell # Windows — disable a service Set-Service -Name "Spooler" -StartupType Disabled Stop-Service -Name "Spooler" -Force # Disable via sc.exe (works in older environments) sc.exe config "RemoteRegistry" start= disabled sc.exe stop "RemoteRegistry" # Disable multiple unnecessary services (example hardening script) $servicesToDisable = @( "Fax", "XblAuthManager", "XblGameSave", "XboxGipSvc", "XboxNetApiSvc", "RemoteRegistry", "SharedAccess", "SNMP" ) foreach ($svc in $servicesToDisable) { if (Get-Service -Name $svc -ErrorAction SilentlyContinue) { Set-Service -Name $svc -StartupType Disabled -ErrorAction SilentlyContinue Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue Write-Host "Disabled: $svc" } } Host-Based Firewall Configuration ----------------------------------- Even after disabling services, a host-based firewall provides an independent layer of protection, blocking inbound connections to any port regardless of what is listening. .. code-block:: bash # UFW (Uncomplicated Firewall) — Ubuntu sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp comment "SSH" sudo ufw allow 443/tcp comment "HTTPS" sudo ufw enable sudo ufw status verbose # firewalld — RHEL/CentOS/Rocky sudo firewall-cmd --set-default-zone=drop sudo firewall-cmd --zone=public --add-service=ssh --permanent sudo firewall-cmd --zone=public --add-service=https --permanent sudo firewall-cmd --reload sudo firewall-cmd --list-all # iptables — direct (lower-level) # Flush existing rules sudo iptables -F sudo iptables -X # Default deny sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP sudo iptables -P OUTPUT ACCEPT # Allow established connections sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow loopback sudo iptables -A INPUT -i lo -j ACCEPT # Allow SSH sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Save rules sudo iptables-save | sudo tee /etc/iptables/rules.v4 .. code-block:: powershell # Windows Defender Firewall — enable all profiles Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True # Set default inbound action to block Set-NetFirewallProfile -Profile Domain,Public,Private -DefaultInboundAction Block # Allow RDP only from management subnet New-NetFirewallRule -DisplayName "Allow RDP from Mgmt" ` -Direction Inbound -Protocol TCP -LocalPort 3389 ` -RemoteAddress "10.10.0.0/24" -Action Allow # Block a specific port New-NetFirewallRule -DisplayName "Block Telnet" ` -Direction Inbound -Protocol TCP -LocalPort 23 -Action Block # Export current firewall rules for documentation Get-NetFirewallRule | Where-Object { $_.Enabled -eq "True" } | Select-Object DisplayName, Direction, Action, Profile | Export-Csv -Path "firewall_rules_$(Get-Date -Format yyyyMMdd).csv" -NoTypeInformation ---- User Account and Authentication Hardening ========================================== Default Account Elimination ----------------------------- Default accounts — particularly those with well-known credentials — are among the most exploited weaknesses in deployed systems. The CISA Known Exploited Vulnerabilities (KEV) catalogue is littered with entries that trace back to unchanged default passwords. .. code-block:: bash # Linux — disable root login (use sudo instead) sudo passwd -l root # lock the root account sudo usermod -s /sbin/nologin root # set shell to nologin # List all accounts with UID 0 (should only be root, or empty if root locked) awk -F: '($3 == "0") { print $1 }' /etc/passwd # Find accounts with no password set sudo awk -F: '($2 == "" ) { print $1 }' /etc/shadow # Lock inactive accounts sudo passwd -l olduser sudo usermod --expiredate 1 olduser # expire immediately # List users who can log in (have a valid shell) grep -vE '(/nologin|/false)$' /etc/passwd .. code-block:: powershell # Windows — rename the built-in Administrator account Rename-LocalUser -Name "Administrator" -NewName "SvcAdmin_Renamed" # Disable the built-in Guest account Disable-LocalUser -Name "Guest" # List all local users and their status Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordLastSet # Disable stale accounts (not logged in for 90 days) $cutoff = (Get-Date).AddDays(-90) Get-LocalUser | Where-Object { $_.LastLogon -lt $cutoff -and $_.Enabled -eq $true } | Disable-LocalUser Password Policies ----------------- Strong password policies reduce the effectiveness of credential-based attacks, including brute force, password spraying, and credential stuffing. .. rubric:: Recommended Minimum Password Policy (NIST SP 800-63B aligned) - **Minimum length**: 12 characters (15+ for privileged accounts) - **Complexity**: Not required if length ≥ 15 (length is more valuable) - **History**: Prevent reuse of last 12 passwords - **Maximum age**: 365 days for standard accounts; consider no expiry with MFA - **Lockout**: 5–10 failed attempts triggers 15–30 minute lockout or admin unlock - **Breached password check**: Reject passwords found in known breach databases .. code-block:: bash # Linux — configure PAM password quality (Ubuntu/Debian) sudo apt install libpam-pwquality # Edit /etc/security/pwquality.conf minlen = 14 minclass = 3 maxrepeat = 3 maxsequence = 4 gecoscheck = 1 dictcheck = 1 # Configure account lockout via pam_faillock # Edit /etc/pam.d/common-auth — add before pam_unix: auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900 # Configure password aging via /etc/login.defs sudo sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 365/' /etc/login.defs sudo sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' /etc/login.defs sudo sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' /etc/login.defs # Apply aging to existing accounts sudo chage -M 365 -m 1 -W 14 username .. code-block:: powershell # Windows — configure local password policy # (Use Group Policy for domain environments) # Set minimum password length to 14 net accounts /minpwlen:14 # Set password history to 24 passwords net accounts /uniquepw:24 # Set maximum password age to 365 days net accounts /maxpwage:365 # Set lockout threshold to 5 attempts, lockout duration 30 min net accounts /lockoutthreshold:5 /lockoutduration:30 /lockoutwindow:30 # View current policy net accounts Multi-Factor Authentication (MFA) ----------------------------------- Even strong passwords can be stolen via phishing, keyloggers, or database breaches. MFA requires attackers to compromise a second factor — significantly raising the cost of account takeover. **Linux — Google Authenticator PAM (TOTP-based MFA for SSH)** .. code-block:: bash # Install sudo apt install libpam-google-authenticator # Configure for each user (run as the target user) google-authenticator # Edit /etc/pam.d/sshd — add at the top: auth required pam_google_authenticator.so # Edit /etc/ssh/sshd_config: ChallengeResponseAuthentication yes UsePAM yes AuthenticationMethods publickey,keyboard-interactive sudo systemctl restart sshd SSH Hardening -------------- SSH is the primary remote administration protocol for Linux systems. Its default configuration is functional but not secure. .. code-block:: bash # /etc/ssh/sshd_config — recommended hardening settings # Disable root login over SSH PermitRootLogin no # Require SSH key authentication; disable password auth PasswordAuthentication no PubkeyAuthentication yes # Disable legacy protocol and weak ciphers Protocol 2 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 KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org # Restrict access to specific users or groups AllowUsers alice bob # AllowGroups sshusers # Set idle timeout (seconds) — disconnect idle sessions after 15 minutes ClientAliveInterval 300 ClientAliveCountMax 3 # Disable X11 and agent forwarding unless explicitly needed X11Forwarding no AllowAgentForwarding no # Change default port to reduce automated scanning (security through obscurity) # Port 2222 # Optional; note this is not a substitute for proper controls # Enable strict mode StrictModes yes # Limit authentication attempts MaxAuthTries 3 MaxSessions 4 # Log level LogLevel VERBOSE # Apply and verify sudo sshd -t && sudo systemctl restart sshd ---- Filesystem and Permission Hardening ===================================== File Permission Principles --------------------------- Improper file permissions are a common pathway for privilege escalation. An attacker who compromises a low-privilege account can use world-writable files, SUID/SGID binaries, and misconfigured directories to move toward root. .. rubric:: Linux Permission Reference .. code-block:: text Permission Bits: r (4) = read w (2) = write x (1) = execute Example: -rwxr-x--- = owner:rwx, group:r-x, others:--- Special bits: SUID (4000): Execute as file owner (e.g., passwd, sudo) SGID (2000): Execute as file group Sticky (1000): Only owner can delete files in directory (e.g., /tmp) .. code-block:: bash # Find world-writable files (potential risk) sudo find / -xdev -perm -002 -type f 2>/dev/null | grep -v /proc # Find world-writable directories sudo find / -xdev -perm -002 -type d 2>/dev/null # Find SUID/SGID binaries (audit these carefully) sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null # Find files with no owner (orphaned — potential indicator of compromise) sudo find / -xdev \( -nouser -o -nogroup \) -type f 2>/dev/null # Correct permissions on sensitive files sudo chmod 600 /etc/shadow # readable only by root sudo chmod 644 /etc/passwd # readable by all, writable only by root sudo chmod 600 /etc/ssh/sshd_config sudo chmod 700 /root # root home directory # Remove SUID from unnecessary binaries sudo chmod u-s /usr/bin/at # if the 'at' scheduler is not needed # Set immutable flag on critical config files sudo chattr +i /etc/passwd /etc/shadow /etc/group Filesystem Mount Options ------------------------- Linux mount options can restrict what is permitted within specific filesystems, adding defence-in-depth even if an attacker gains write access. .. code-block:: bash # /etc/fstab hardening examples # # noexec — prevent execution of binaries on this filesystem # nosuid — ignore SUID/SGID bits # nodev — prevent creation/use of device files # # Apply to /tmp (writable by all users) tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=2G 0 0 # # Apply to /var/tmp /var/tmp none bind defaults,noexec,nosuid,nodev,bind 0 0 # # Apply to removable media /dev/sdb1 /media/usb vfat defaults,noexec,nosuid,nodev,noauto,user 0 0 # Remount /tmp with restrictions immediately (without rebooting) sudo mount -o remount,noexec,nosuid,nodev /tmp NTFS Permissions and Windows Hardening ---------------------------------------- On Windows, the NTFS permission model provides granular access control. Hardening focuses on removing excessive permissions from the filesystem, particularly on system directories. .. code-block:: powershell # List NTFS permissions on a directory Get-Acl -Path "C:\inetpub\wwwroot" | Format-List # Restrict write access on a sensitive directory $acl = Get-Acl -Path "C:\Windows\System32\drivers\etc" # Remove all non-inherited access for Users group $acl.Access | Where-Object { $_.IdentityReference -match "Users" } | ForEach-Object { $acl.RemoveAccessRule($_) } Set-Acl -Path "C:\Windows\System32\drivers\etc" -AclObject $acl # Audit access to sensitive files (enable auditing on object) $auditRule = New-Object System.Security.AccessControl.FileSystemAuditRule( "Everyone", "FullControl", "ContainerInherit,ObjectInherit", "None", "Success,Failure" ) $acl = Get-Acl "C:\SensitiveData" $acl.SetAuditRule($auditRule) Set-Acl -Path "C:\SensitiveData" -AclObject $acl ---- Operating System Kernel and Core Hardening =========================================== Linux Kernel Parameters (sysctl) ---------------------------------- The Linux kernel exposes hundreds of tunable parameters via ``/proc/sys``, configurable persistently through ``/etc/sysctl.conf`` or ``/etc/sysctl.d/*.conf``. Many of these directly affect security. .. code-block:: bash # /etc/sysctl.d/99-hardening.conf # ─── Network Hardening ─────────────────────────────────────────────────── # Disable IP forwarding (unless this host is a router) net.ipv4.ip_forward = 0 net.ipv6.conf.all.forwarding = 0 # Disable packet acceptance from hosts not in routing table (source routing) net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Ignore ICMP redirects (prevents MITM via fake routing updates) net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 # Enable reverse path filtering (drop packets with impossible source IPs) net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Protect against SYN flood attacks net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # Ignore broadcast ICMP (Smurf attack prevention) net.ipv4.icmp_echo_ignore_broadcasts = 1 # Log martian packets (packets with impossible source addresses) net.ipv4.conf.all.log_martians = 1 # ─── Memory and Execution Hardening ───────────────────────────────────── # Enable ASLR (Address Space Layout Randomisation) — full randomisation kernel.randomize_va_space = 2 # Restrict kernel pointer exposure in /proc (prevents info leaks) kernel.kptr_restrict = 2 # Restrict access to kernel logs to root only kernel.dmesg_restrict = 1 # Restrict ptrace (prevent process inspection by other processes) kernel.yama.ptrace_scope = 1 # Disable magic SysRq key (can be used to bypass security controls) kernel.sysrq = 0 # ─── File System Hardening ─────────────────────────────────────────────── # Prevent hardlinks to files you don't own fs.protected_hardlinks = 1 fs.protected_symlinks = 1 # Prevent core dumps from SUID processes fs.suid_dumpable = 0 # Apply all settings immediately sudo sysctl -p /etc/sysctl.d/99-hardening.conf Mandatory Access Control (MAC) -------------------------------- Traditional Linux uses Discretionary Access Control (DAC): owners set permissions, and root overrides all. MAC frameworks enforce security policies even on processes running as root, confining them to only what the policy explicitly permits. **SELinux** (Security-Enhanced Linux — RHEL, Fedora, Rocky) .. code-block:: bash # Check SELinux status sestatus getenforce # Set to enforcing mode (production target) sudo setenforce 1 # immediate sudo sed -i 's/SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config # persistent # View denial logs sudo ausearch -m avc -ts recent | audit2why # Generate a policy module for a legitimate application denial sudo ausearch -m avc -ts recent | audit2allow -M myapp sudo semodule -i myapp.pp # List contexts for a file ls -Z /var/www/html # Restore default context on a file sudo restorecon -Rv /var/www/html **AppArmor** (Ubuntu, Debian, SUSE) .. code-block:: bash # Check AppArmor status sudo aa-status # Set a profile to enforce mode sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx # Set a profile to complain mode (log but don't block — useful for testing) sudo aa-complain /etc/apparmor.d/usr.sbin.nginx # View AppArmor denials sudo dmesg | grep "apparmor=\"DENIED\"" # Generate a profile for a new application sudo aa-genprof /usr/bin/myapp Windows Security Policies --------------------------- Group Policy (or Local Security Policy on standalone systems) is the primary mechanism for enforcing OS-level security controls on Windows. .. code-block:: powershell # Audit Policy — enable auditing of key security events auditpol /set /subcategory:"Logon" /success:enable /failure:enable auditpol /set /subcategory:"Account Lockout" /failure:enable auditpol /set /subcategory:"Privilege Use" /success:enable /failure:enable auditpol /set /subcategory:"Process Creation" /success:enable auditpol /set /subcategory:"Object Access" /success:enable /failure:enable # Verify audit policy auditpol /get /category:* # Disable LLMNR (Link-Local Multicast Name Resolution — exploited by Responder) New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Force Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" ` -Name "EnableMulticast" -Value 0 # Disable NetBIOS over TCP/IP $adapters = Get-WmiObject Win32_NetworkAdapterConfiguration foreach ($adapter in $adapters) { $adapter.SetTcpipNetbios(2) # 2 = Disable NetBIOS over TCP/IP } # Enable Windows Defender Credential Guard (requires UEFI + Virtualisation) # This protects LSASS memory from credential dumping tools like Mimikatz Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard" ` -Name "EnableVirtualizationBasedSecurity" -Value 1 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" ` -Name "LsaCfgFlags" -Value 1 # 1 = Credential Guard without UEFI lock # Disable SMBv1 (exploited by EternalBlue/WannaCry) Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol # Require SMB signing (prevents relay attacks) Set-SmbServerConfiguration -RequireSecuritySignature $true -Force Set-SmbClientConfiguration -RequireSecuritySignature $true -Force ---- Logging, Auditing, and Monitoring =================================== Why Logging Is a Hardening Control ------------------------------------- Hardening reduces the probability of compromise; logging and monitoring reduce the *dwell time* — the interval between initial compromise and detection. Studies consistently show that the median attacker dwell time before detection is measured in days to weeks. Comprehensive, centralised logging is the foundation of any detection capability. Security-relevant log sources include: - Authentication events (successful and failed logins) - Privilege use and escalation - Process creation and termination - Network connection establishment - File access on sensitive paths - Configuration changes - Service start/stop Linux Logging Configuration ----------------------------- .. code-block:: bash # Install and configure auditd (Linux Audit Framework) sudo apt install auditd audispd-plugins # Ubuntu sudo dnf install audit # RHEL # /etc/audit/rules.d/hardening.rules # Delete all existing rules -D # Set buffer size -b 8192 # Failure mode: 1=log, 2=panic -f 1 # Monitor authentication files -w /etc/passwd -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/group -p wa -k identity -w /etc/sudoers -p wa -k sudoers # Monitor login/logout events -w /var/log/lastlog -p wa -k logins -w /var/run/faillock -p wa -k logins # Monitor privileged command execution -a always,exit -F arch=b64 -S execve -F euid=0 -k privileged # Monitor network configuration changes -a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale -w /etc/hosts -p wa -k system-locale -w /etc/network -p wa -k system-locale # Monitor systemd service changes -w /bin/systemctl -p x -k systemd -w /etc/systemd -p wa -k systemd # Monitor cron -w /etc/cron.d -p wa -k cron -w /etc/cron.daily -p wa -k cron -w /var/spool/cron -p wa -k cron # Monitor kernel module loading (rootkit indicator) -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 # Apply rules sudo augenrules --load sudo systemctl restart auditd # Query audit log sudo ausearch -k identity -ts today sudo ausearch -k privileged -i | tail -50 Configuring rsyslog for Centralised Logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash # Forward all logs to a central syslog server # /etc/rsyslog.d/50-forward.conf # TCP forwarding (reliable, encrypted with TLS) *.* @@siem.example.com:514 # Alternatively, forward via TCP with TLS (recommended): $DefaultNetstreamDriver gtls $DefaultNetstreamDriverCAFile /etc/ssl/certs/siem-ca.pem $ActionSendStreamDriverAuthMode x509/name $ActionSendStreamDriverPermittedPeer siem.example.com *.* @@(o)siem.example.com:6514 sudo systemctl restart rsyslog Windows Event Logging ---------------------- .. code-block:: powershell # Increase Windows Event Log sizes (recommended minimums) Limit-EventLog -LogName Security -MaximumSize 1GB Limit-EventLog -LogName System -MaximumSize 512MB Limit-EventLog -LogName Application -MaximumSize 512MB # Key Windows Security Event IDs to monitor: # 4624 - Successful logon # 4625 - Failed logon (brute force indicator) # 4648 - Logon with explicit credentials (pass-the-hash indicator) # 4672 - Special privileges assigned (admin logon) # 4720 - User account created # 4726 - User account deleted # 4732 - Member added to security-enabled local group # 4740 - Account locked out # 4771 - Kerberos pre-authentication failed # 7045 - New service installed (malware persistence indicator) # 4698 - Scheduled task created # Query for failed logon events in the last 24 hours Get-WinEvent -FilterHashtable @{ LogName = 'Security' Id = 4625 StartTime = (Get-Date).AddHours(-24) } | Select-Object TimeCreated, @{N="Account";E={$_.Properties[5].Value}}, @{N="Source IP";E={$_.Properties[19].Value}} | Format-Table -AutoSize # Enable PowerShell Script Block Logging (detects malicious PS scripts) $PSLogging = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" New-Item -Path $PSLogging -Force Set-ItemProperty -Path $PSLogging -Name "EnableScriptBlockLogging" -Value 1 Set-ItemProperty -Path $PSLogging -Name "EnableScriptBlockInvocationLogging" -Value 1 ---- Application Hardening ====================== Remove Unnecessary Software ----------------------------- Every installed application is a potential attack vector. Applications that are not in use should be removed, not merely disabled, to eliminate their vulnerability footprint entirely. .. code-block:: bash # Ubuntu — list explicitly installed packages apt list --installed 2>/dev/null | wc -l # Remove packages that are rarely needed on servers sudo apt purge telnet ftp rsh-client rsh-redone-client \ talk ntalk nfs-common nis at cups-* avahi-daemon \ postfix sendmail xinetd # Remove orphaned dependencies sudo apt autoremove --purge .. code-block:: powershell # Windows — list installed applications Get-WmiObject Win32_Product | Select-Object Name, Version | Sort-Object Name | Format-Table -AutoSize # Uninstall via WMIC $app = Get-WmiObject Win32_Product | Where-Object { $_.Name -like "*Telnet*" } $app.Uninstall() # Disable Windows features that are not required $features = @( "TelnetClient", "TFTP", "SMB1Protocol", "MicrosoftWindowsPowerShellV2Root", "WindowsMediaPlayer" ) foreach ($f in $features) { Disable-WindowsOptionalFeature -Online -FeatureName $f -NoRestart } Web Server Hardening (nginx example) -------------------------------------- Web servers require specific hardening beyond the OS baseline because they are directly exposed to untrusted input from the internet. .. code-block:: nginx # /etc/nginx/nginx.conf — security-focused configuration # Hide nginx version information server_tokens off; # Prevent MIME type sniffing add_header X-Content-Type-Options "nosniff" always; # Enable XSS filter in older browsers add_header X-XSS-Protection "1; mode=block" always; # Prevent clickjacking add_header X-Frame-Options "SAMEORIGIN" always; # Enforce HTTPS (only add after confirming HTTPS is working) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Content Security Policy add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'" always; # Restrict HTTP methods if ($request_method !~ ^(GET|HEAD|POST)$) { return 405; } # Disable directory listing autoindex off; # Rate limiting limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; limit_req zone=api burst=20 nodelay; # TLS hardening ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_stapling on; ssl_stapling_verify on; Database Hardening (PostgreSQL example) ----------------------------------------- .. code-block:: sql -- Remove default and test databases DROP DATABASE IF EXISTS test; -- Create dedicated application user with minimal privileges CREATE USER appuser WITH PASSWORD 'use_a_strong_generated_password'; GRANT CONNECT ON DATABASE appdb TO appuser; GRANT USAGE ON SCHEMA public TO appuser; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser; -- Revoke public schema creation from PUBLIC role REVOKE CREATE ON SCHEMA public FROM PUBLIC; REVOKE ALL ON DATABASE appdb FROM PUBLIC; -- Enable SSL connections only -- In postgresql.conf: -- ssl = on -- ssl_cert_file = 'server.crt' -- ssl_key_file = 'server.key' -- Log all connection attempts -- In postgresql.conf: -- log_connections = on -- log_disconnections = on -- log_failed_authentications = on .. code-block:: bash # pg_hba.conf — restrict connection methods # Only allow application user from application server subnet, SSL required # TYPE DATABASE USER ADDRESS METHOD local all postgres peer host appdb appuser 10.0.1.0/24 scram-sha-256 # Reject everything else host all all 0.0.0.0/0 reject ---- Vulnerability Scanning and Compliance Verification =================================================== After applying hardening controls, verification is essential. Manual review does not scale; automated scanning tools are required. OpenSCAP (Linux) ----------------- SCAP (Security Content Automation Protocol) enables automated compliance assessment against CIS and STIG benchmarks. .. code-block:: bash # Install OpenSCAP sudo apt install libopenscap8 ssg-base ssg-debderived # Ubuntu sudo dnf install openscap-scanner scap-security-guide # RHEL # List available profiles oscap info /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml # Run CIS Level 1 assessment and generate HTML report sudo oscap xccdf eval \ --profile xccdf_org.ssgproject.content_profile_cis_level1_server \ --results scan-results.xml \ --report scan-report.html \ /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml # View overall score grep "score" scan-results.xml | head -5 # Remediate failed controls automatically (use with caution in production) sudo oscap xccdf eval \ --profile xccdf_org.ssgproject.content_profile_cis_level1_server \ --remediate \ /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml Lynis (Cross-Platform Audit Tool) ----------------------------------- Lynis is a lightweight, agentless security audit tool that does not require a specific profile — it performs comprehensive checks and provides recommendations. .. code-block:: bash # Install sudo apt install lynis # or download from cisofy.com # Run a full system audit sudo lynis audit system # Run and save results to a log file sudo lynis audit system --logfile /var/log/lynis.log \ --report-file /var/log/lynis-report.dat # View hardening index score grep "hardening_index" /var/log/lynis-report.dat # Focus on a specific category sudo lynis audit system --tests-category "authentication" # Non-interactive mode for CI/CD integration sudo lynis audit system --quick --quiet --no-colors Microsoft Security Compliance Toolkit (Windows) ------------------------------------------------- .. code-block:: powershell # Download and use the Policy Analyser to compare current settings # to Microsoft Security Baselines # Example: Check if key baseline settings are applied function Test-SecurityBaseline { $results = @() # Check SMBv1 $smb1 = (Get-SmbServerConfiguration).EnableSMB1Protocol $results += [PSCustomObject]@{ Control = "SMBv1 Disabled" Status = if (-not $smb1) { "PASS" } else { "FAIL" } } # Check Windows Firewall $fw = Get-NetFirewallProfile | Where-Object { $_.Enabled -eq $false } $results += [PSCustomObject]@{ Control = "All Firewall Profiles Enabled" Status = if (-not $fw) { "PASS" } else { "FAIL" } } # Check Credential Guard $cg = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" ` -Name "LsaCfgFlags" -ErrorAction SilentlyContinue).LsaCfgFlags $results += [PSCustomObject]@{ Control = "Credential Guard Enabled" Status = if ($cg -ge 1) { "PASS" } else { "FAIL" } } $results | Format-Table -AutoSize } Test-SecurityBaseline ---- Hardening in the Software Development Lifecycle ================================================= Hardening is not only an operational concern; it must be embedded throughout the SDLC to avoid technical debt accumulating in deployed systems. Infrastructure as Code (IaC) Hardening ----------------------------------------- When infrastructure is provisioned via IaC (Terraform, Ansible, CloudFormation), security controls should be expressed in code and version-controlled. .. code-block:: yaml # Ansible playbook excerpt — applying hardening to a new Ubuntu host --- - name: System Hardening Baseline hosts: all become: yes tasks: - name: Ensure SSH PermitRootLogin is disabled lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PermitRootLogin' line: 'PermitRootLogin no' validate: 'sshd -t -f %s' notify: Restart sshd - name: Disable unnecessary services systemd: name: "{{ item }}" state: stopped enabled: no masked: yes loop: - bluetooth - avahi-daemon - cups ignore_errors: yes - name: Apply sysctl hardening parameters sysctl: name: "{{ item.key }}" value: "{{ item.value }}" state: present reload: yes loop: - { key: "kernel.randomize_va_space", value: "2" } - { key: "net.ipv4.tcp_syncookies", value: "1" } - { key: "net.ipv4.conf.all.rp_filter", value: "1" } - { key: "fs.protected_hardlinks", value: "1" } - { key: "kernel.kptr_restrict", value: "2" } - name: Set password hashing rounds in /etc/login.defs lineinfile: path: /etc/login.defs regexp: '^#?SHA_CRYPT_MIN_ROUNDS' line: 'SHA_CRYPT_MIN_ROUNDS 65536' handlers: - name: Restart sshd systemd: name: sshd state: restarted Container Hardening -------------------- Containers present a distinct attack surface. While they share the host kernel (unlike VMs), they can be hardened to reduce the blast radius of a container escape or application compromise. .. code-block:: dockerfile # Dockerfile hardening best practices # Use a minimal base image (distroless or alpine) FROM gcr.io/distroless/base-debian12 # Run as a non-root user RUN groupadd -r appgroup && useradd -r -g appgroup appuser USER appuser # Copy only what is needed (avoid COPY . .) COPY --chown=appuser:appgroup ./app /app # Use WORKDIR (never use / as working directory) WORKDIR /app # Don't expose unnecessary ports EXPOSE 8080 # Set a read-only filesystem via runtime flags # docker run --read-only --tmpfs /tmp myimage .. code-block:: bash # Runtime hardening flags for Docker docker run \ --read-only \ # read-only root filesystem --tmpfs /tmp \ # writable tmpfs for /tmp only --no-new-privileges \ # prevent privilege escalation --cap-drop ALL \ # drop all Linux capabilities --cap-add NET_BIND_SERVICE \ # re-add only what's needed --security-opt no-new-privileges:true \ --security-opt seccomp=./seccomp.json \ # custom seccomp profile -u 1000:1000 \ # run as non-root UID/GID --memory 512m \ # limit memory --cpus 1.0 \ # limit CPU myapp:latest ---- Case Study: Hardening a Newly Provisioned Web Server ====================================================== This case study walks through applying hardening to a freshly installed Ubuntu 22.04 server designated to run a Python web application behind nginx. Initial State Assessment -------------------------- .. code-block:: bash # Run Lynis before hardening to establish baseline sudo lynis audit system --quick 2>&1 | grep "Hardening index" # Example output: Hardening index : 55 [########### ] # Document listening ports sudo ss -tlnp # Before hardening, typical output shows: # LISTEN 0 128 0.0.0.0:22 (ssh) # LISTEN 0 128 0.0.0.0:25 (postfix — installed but not needed) # LISTEN 0 128 0.0.0.0:111 (rpcbind — installed but not needed) Applying Hardening Steps -------------------------- .. code-block:: bash # Step 1 — Update everything sudo apt update && sudo apt full-upgrade -y # Step 2 — Remove unnecessary packages sudo apt purge postfix rpcbind avahi-daemon cups telnet nfs-kernel-server -y sudo apt autoremove --purge -y # Step 3 — Install and configure UFW firewall sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable # Step 4 — Configure automatic security updates sudo apt install unattended-upgrades -y sudo dpkg-reconfigure -plow unattended-upgrades # Step 5 — SSH hardening (edit /etc/ssh/sshd_config) sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config sudo sed -i 's/^#\?X11Forwarding.*/X11Forwarding no/' /etc/ssh/sshd_config echo "MaxAuthTries 3" | sudo tee -a /etc/ssh/sshd_config sudo sshd -t && sudo systemctl restart sshd # Step 6 — Apply sysctl hardening sudo tee /etc/sysctl.d/99-hardening.conf <<'EOF' kernel.randomize_va_space = 2 net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.icmp_echo_ignore_broadcasts = 1 kernel.kptr_restrict = 2 kernel.dmesg_restrict = 1 fs.protected_hardlinks = 1 fs.protected_symlinks = 1 fs.suid_dumpable = 0 EOF sudo sysctl -p /etc/sysctl.d/99-hardening.conf # Step 7 — Create dedicated application user sudo useradd -r -s /usr/sbin/nologin -d /var/www/myapp webappuser sudo chown -R webappuser:webappuser /var/www/myapp # Step 8 — Install and enable auditd sudo apt install auditd -y sudo systemctl enable --now auditd # Step 9 — Lock root account sudo passwd -l root Post-Hardening Verification ------------------------------ .. code-block:: bash # Verify no unexpected listening ports remain sudo ss -tlnp # Expected: only :22, :80, :443 # Re-run Lynis sudo lynis audit system --quick 2>&1 | grep "Hardening index" # Expected improvement, e.g.: Hardening index : 76 [############### ] # Test firewall sudo ufw status verbose # Confirm SSH root login blocked ssh root@localhost # should be rejected ---- Summary and Key Takeaways ========================== System hardening is not a one-time project but an ongoing discipline that must be woven into operational processes, change management, and the software development lifecycle. The following principles underpin every hardening activity covered in this chapter: 1. **Reduce attack surface proactively.** Remove what you do not need; disable what you cannot remove; restrict what you cannot disable. 2. **Apply least privilege everywhere.** Users, processes, services, and containers should all operate with the minimum permissions required. 3. **Use established benchmarks.** CIS Benchmarks and DISA STIGs represent the distilled expertise of large security communities — leverage them. 4. **Patch continuously.** Unpatched vulnerabilities are the most reliably exploited weakness; automated patch management is a necessity, not a luxury. 5. **Verify your controls.** Apply, then scan. Use tools like Lynis, OpenSCAP, and Windows Security Compliance Toolkit to confirm controls are actually in place. 6. **Log and monitor.** Hardening reduces the probability of compromise; comprehensive logging reduces dwell time when compromise occurs. 7. **Automate and codify.** Hardening applied manually drifts; hardening expressed in Ansible playbooks, Terraform modules, and Dockerfiles is repeatable, reviewable, and auditable. ---- Review Questions ================ 1. Define "attack surface" and explain the three primary dimensions along which it can be categorised. Provide a real-world example of a hardening control that reduces each dimension. 2. A junior administrator argues that disabling the Guest account and renaming the Administrator account on Windows is "security through obscurity" and therefore not worthwhile. Evaluate this argument. 3. Explain the difference between Discretionary Access Control (DAC) and Mandatory Access Control (MAC). Why is MAC considered a stronger hardening control, and what are its operational trade-offs? 4. You discover that a web server's ``nginx`` process is running as root. Describe the steps you would take to remediate this and explain why it matters. 5. A CIS Benchmark check reports that ``kernel.randomize_va_space`` is set to ``0``. What attack class does this misconfiguration enable, and how would you remediate it? 6. Design a patch management SLA framework for an organisation that runs a mix of internet-facing web servers, internal HR systems, and manufacturing floor SCADA systems. Justify your SLA choices for each category. 7. Compare OpenSCAP and Lynis as hardening verification tools. In what scenarios would you choose one over the other? ---- Practical Exercises =================== .. rubric:: Exercise 1 — Service Inventory and Reduction Provision a fresh Ubuntu 22.04 virtual machine (or use a provided lab environment). Perform the following: a. Document all listening ports using ``ss -tlnp``. b. For each service identified, research its purpose and determine whether it is required for a web server role. c. Disable all non-essential services. d. Confirm the change by re-running the port scan. e. Take a screenshot showing before and after states. .. rubric:: Exercise 2 — SSH Hardening On the same lab system: a. Apply all SSH hardening settings from the ``sshd_config`` example in this chapter. b. Test that root login is blocked. c. Configure key-based authentication for your user account. d. Test that password authentication is rejected. e. Verify the configuration is syntactically valid using ``sshd -t``. .. rubric:: Exercise 3 — Lynis Baseline and Improvement a. Run ``lynis audit system`` and record the Hardening Index score. b. Identify the top five suggestions in the output. c. Implement at least three of the recommendations. d. Re-run Lynis and document the change in score. e. Write a brief justification for any suggestion you chose not to implement. .. rubric:: Exercise 4 — Firewall Configuration a. Configure UFW (or iptables) to allow only SSH (port 22) and HTTPS (port 443) inbound. b. Use ``nmap`` from a second machine (or loopback) to verify only the expected ports respond. c. Add a rule to allow SSH only from a specific IP address (use ``127.0.0.1`` if working on a single machine). d. Document your final rule set. .. rubric:: Exercise 5 — Audit Logging a. Configure ``auditd`` with rules to monitor ``/etc/passwd``, ``/etc/shadow``, and ``/etc/sudoers`` for write access. b. As root, make a benign change to ``/etc/sudoers`` (add and then immediately remove a comment line). c. Use ``ausearch`` to retrieve the audit events generated. d. Identify what information the audit record contains (who, what, when). ---- Further Reading and References ================================ - Center for Internet Security. *CIS Benchmarks*. https://www.cisecurity.org/cis-benchmarks - National Institute of Standards and Technology. *NIST SP 800-123: Guide to General Server Security*. https://doi.org/10.6028/NIST.SP.800-123 - DISA. *Security Technical Implementation Guides (STIGs)*. https://public.cyber.mil/stigs/ - NSA/CISA. *Top 10 Cybersecurity Misconfigurations*. https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-278a - The Linux Audit Project. *auditd documentation*. https://github.com/linux-audit/audit-documentation - OpenSCAP Project. *SCAP Security Guide*. https://www.open-scap.org/ - Cisofy. *Lynis — Security Auditing Tool*. https://cisofy.com/lynis/ - Mozilla. *Server-Side TLS Guidelines*. https://wiki.mozilla.org/Security/Server_Side_TLS - Microsoft. *Windows security baselines*. https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/windows-security-baselines - Docker. *Docker Security*. https://docs.docker.com/engine/security/ ---- .. note:: **Chapter Version:** 1.0 | **Last Reviewed:** April 2026 Commands and procedures in this chapter have been tested on Ubuntu 22.04 LTS and Windows Server 2022. Always test hardening changes in a non- production environment before deploying. Security guidance evolves rapidly; verify recommendations against the latest vendor advisories and benchmark versions before implementation. Unit 4: System Hardening — Multiple Choice Quiz ======================================================== Instructions ============ Select the best answer for each of the following ten questions based on the chapter provided. Reference the listed sections if you need help finding the answer. Questions ========= 1. What is the primary goal of the system hardening process? ------------------------------------------------------------------ A) To maximize system compatibility and ease-of-use for all users. B) To shrink the attack surface to the smallest practical footprint. C) To ensure every service account has local administrator rights. D) To increase the number of active network ports for better connectivity. **Section:** Introduction 2. Which dimension of the attack surface involves "Installed applications, libraries, and unpatched CVEs"? ------------------------------------------------------------------------------------------------------------ A) Network B) Human / Configuration C) Software D) Physical **Section:** The Attack Surface 3. According to the Principle of Least Privilege, how should a web server process be configured? --------------------------------------------------------------------------------------------------- A) It should run as 'root' to ensure it has all necessary permissions. B) It should be part of the Domain Admins group. C) It should operate with the minimum permissions required for its function. D) It should have write access to /etc/shadow for logging purposes. **Section:** The Principle of Least Privilege 4. Which hardening benchmark is described as being mandatory for the US Department of Defense? ------------------------------------------------------------------------------------------------- A) CIS Benchmarks B) DISA STIGs C) NIST SP 800-123 D) Microsoft Secure Baselines **Section:** Hardening Benchmarks and Standards 5. Under a standard Risk-based Patch SLA, what is the target remediation window for a Critical vulnerability (CVSS 9.0 – 10.0)? ------------------------------------------------------------------------------------------------------------------------------------- A) 24 – 72 hours B) 7 – 14 days C) 30 days D) 90 days **Section:** Patch SLA Tiers 6. On a RHEL or Rocky Linux system, which command would you use to apply ONLY security updates? --------------------------------------------------------------------------------------------------- A) ``sudo apt upgrade`` B) ``sudo dnf update`` C) ``sudo dnf update --security`` D) ``sudo systemctl start security-patch`` **Section:** Linux Patch Management 7. Which Windows service is associated with the "PrintNightmare" vulnerability and should be disabled if unnecessary? ------------------------------------------------------------------------------------------------------------------------- A) Remote Registry B) Print Spooler C) SNMP v1 D) Fax **Section:** Service and Port Management 8. In Linux service management, what is the effect of the ``systemctl mask`` command? ---------------------------------------------------------------------------------------- A) It temporarily stops the service until the next reboot. B) It renames the service to hide it from attackers. C) It prevents the service from being started, even by other services. D) It enables multi-factor authentication for that service. **Section:** Service and Port Management 9. What is the NIST SP 800-63B aligned recommendation for minimum password length for standard accounts? ------------------------------------------------------------------------------------------------------------- A) 8 characters B) 10 characters C) 12 characters D) 15 characters **Section:** Password Policies 10. Which Linux mount option prevents the execution of binaries on a specific filesystem? -------------------------------------------------------------------------------------------- A) ``nosuid`` B) ``nodev`` C) ``noexec`` D) ``ro`` **Section:** Filesystem Mount Options ---- Answer Key ========== 1. **B** 2. **C** 3. **C** 4. **B** 5. **A** 6. **C** 7. **B** 8. **C** 9. **C** 10. **C**