Lab 06: Linux Security Hardening

Time: 40 minutes | Level: Advanced | Docker: docker run -it --rm --privileged ubuntu:22.04 bash

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)
systemctl list-units --type=service --state=running 2>/dev/null || echo "systemd not active in container"

# Check open ports
ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null

# Check current kernel parameters
sysctl kernel.randomize_va_space
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.accept_redirects

📸 Verified Output:

$ docker run --rm ubuntu:22.04 bash -c "sysctl kernel.randomize_va_space net.ipv4.ip_forward 2>/dev/null"
kernel.randomize_va_space = 2
net.ipv4.ip_forward = 1

💡 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.

📸 Verified Output:


Summary

Topic
Tool / File
Key Setting

SSH hardening

/etc/ssh/sshd_config

PermitRootLogin no, MaxAuthTries 3, AllowUsers

Password aging

/etc/login.defs

PASS_MAX_DAYS 90, PASS_MIN_DAYS 7

Password complexity

/etc/security/pwquality.conf

minlen=14, minclass=4

ASLR

sysctl kernel.randomize_va_space

= 2 (full randomization)

Network hardening

/etc/sysctl.d/99-hardening.conf

Disable redirects, enable SYN cookies

File locking

chattr +i <file>

Immutable bit blocks all writes

Default deny

/etc/hosts.deny

ALL: ALL

umask hardening

/etc/profile

umask 027

Last updated