Security hardening reduces your attack surface by eliminating unnecessary services, enforcing strict authentication policies, and configuring the kernel to resist exploitation. This lab follows CIS Benchmark principles and covers SSH hardening, password policy, kernel parameters, file attribute locking, and TCP wrappers.
Step 1: Audit the Current System State
Before hardening, understand what you're working with.
# Check running services (in a real system)systemctllist-units--type=service--state=running2>/dev/null||echo"systemd not active in container"# Check open portsss-tlnp2>/dev/null||netstat-tlnp2>/dev/null# Check current kernel parameterssysctlkernel.randomize_va_spacesysctlnet.ipv4.ip_forwardsysctlnet.ipv4.conf.all.accept_redirects
💡 kernel.randomize_va_space = 2 means full ASLR is enabled — memory addresses are randomized, making buffer overflow exploits much harder to execute reliably.
Step 2: SSH Hardening — sshd_config
SSH is the primary remote access vector. Lock it down.
📸 Verified Output:
Apply hardened settings:
📸 Verified Output (after edits):
💡 AllowUsers creates an explicit allowlist. Any account not listed is denied SSH access even with valid credentials — this is a critical defense-in-depth layer.
Step 3: Password Policy — /etc/login.defs
Configure system-wide password aging and length defaults.
📸 Verified Output:
Apply CIS-compliant password aging:
💡 login.defs changes only affect new accounts. Apply chage to existing users: chage --maxdays 90 --mindays 7 --warndays 14 username
Step 4: PAM Password Quality — libpam-pwquality
Enforce password complexity via PAM.
📸 Verified Output:
💡 minclass = 4 requires all four character classes: uppercase, lowercase, digits, and symbols. This makes passwords far more resistant to dictionary attacks.
Step 5: Kernel Hardening via sysctl
Harden the kernel against network attacks and memory exploits.
📸 Verified Output:
Create a persistent hardening configuration:
Step 6: File Attribute Locking with chattr
Prevent modification of critical config files — even by root.
📸 Verified Output:
💡 chattr +i sets the immutable bit at the filesystem level. Even rm -f fails. Use it to protect /etc/passwd, /etc/shadow, /etc/sudoers after hardening.
Step 7: umask Hardening and /etc/hosts.deny
Tighten default file permissions and configure TCP wrappers.
📸 Verified Output:
📸 Verified Output:
💡 TCP wrappers (/etc/hosts.allow and /etc/hosts.deny) provide network-level access control before a service even accepts a connection. Use hosts.deny: ALL: ALL as a baseline deny-all policy.
Step 8: Capstone — Harden a Fresh Ubuntu Server
Scenario: Your team just provisioned a new Ubuntu 22.04 server exposed to the internet. You need to apply full CIS-level hardening before it goes into production.