scipio avatar

Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress

scipio

Published: 29 Jun 2026 › Updated: 29 Jun 2026Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress

Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress

Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress

leh-banner.jpg

What will I learn

  • Why defaults are dangerous -- what a fresh Linux install exposes and why every service is an attack surface;
  • User and access hardening -- disabling root login, enforcing strong passwords, and configuring PAM;
  • SSH hardening -- key-only authentication, port changes, fail2ban, and MFA for SSH;
  • Filesystem hardening -- mount options, file permissions, SUID auditing, and tmpfs security;
  • Kernel hardening -- sysctl parameters that reduce the attack surface;
  • Firewall configuration -- nftables rules that actually protect, not just exist on paper;
  • AppArmor and SELinux -- mandatory access control that contains compromised services;
  • Automated hardening -- CIS benchmarks, Lynis, and Ansible hardening playbooks.

Requirements

  • A working modern computer running macOS, Windows or Ubuntu;
  • A Linux VM (Ubuntu Server 22.04 or Debian 12 recommended);
  • Root access to the VM;
  • The ambition to learn ethical hacking and security research.

Difficulty

  • Intermediate

Curriculum (of the Learn Ethical Hacking Series):

Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress

Solutions to Episode 70 Exercises

Exercise 1: Pentest proposal (abbreviated).

PROPOSAL: Web Application & Network Penetration Test
Client: Apex E-Commerce Ltd (fictional)
Scope: customer-facing web app (app.apex.com), mobile API,
  internal corporate network (192.168.0.0/16, 3 offices)
Methodology: OWASP Testing Guide (web), PTES (network)
Timeline: 10 business days (May 19-30, 2026)
Deliverables: executive summary, technical report, retest (30 days)
Price: EUR 18,500 (web: 8,500 + network: 10,000)
Terms: NDA signed, ROE signed by CTO, E&O insurance in place,
  data destroyed within 30 days of report delivery.

The proposal structure follows what we discussed in episode 70: scope boundaries are explicit (app.apex.com, the mobile API, and the three-office internal network at 192.168.0.0/16), the methodology references established frameworks (OWASP Testing Guide for web, PTES for network), and the deliverables include a retest window. The pricing with separate line items for web and network testing is important -- it allows the client to understand where the money goes and makes future scope changes easier to negotiate. The terms section covering NDA, signed ROE by the CTO (not some mid-level manager), E&O insurance, and data destruction within 30 days is exactly the legal protection we emphasized. If the CTO signs the rules of engagement, that authorization carries weight. If a random IT technician signed it and the CTO later says "I never authorized this," you have a serious problem regardless of how good your pentest was.

Exercise 2: AD lab attack chain (abbreviated).

External recon -> found VPN portal at vpn.lab.local
Password spray -> user jsmith:Summer2026! (OSINT from LinkedIn)
VPN access -> internal network 192.168.1.0/24
Nmap -> found workstation WS01 (192.168.1.50) with SMB open
Kerberoast -> svc_sql password cracked: SqlAdmin2024!
svc_sql is member of Domain Admins (misconfigured)
Golden Ticket -> persistent Domain Admin access

Time: 4 hours from zero to Domain Admin
All 3 misconfigurations exploited as intended.

Four hours from zero to Domain Admin. That is exactly the kind of attack chain that makes CISOs lose sleep, and the reason we spent an entire episode (episode 33) on Active Directory attacks. The three misconfigurations here are realistic and extremely common in production environments: a weak password surviving a spray attack (episode 7), a Kerberoastable service account with a crackable password, and a service account in the Domain Admins group because "it needs access to everything" (the lazy misconfiguration we see over and over). The Golden Ticket at the end gives persistent access that survives password changes for every account except krbtgt -- which most organizations never rotate. Documenting the exact timestamps and attack path is what transforms this from "I got Domain Admin" into a professional finding that the client can act on. The question "how long did it take?" matters to executives in a way that technical details do not.

Exercise 3: Career roadmap (abbreviated).

Q1: Study for OSCP (3 months, 15 hrs/week)
  Platforms: HTB (5 machines/week), Proving Grounds
  Skills: AD attacks, web exploitation, privesc (Linux + Windows)
Q2: Take OSCP exam. Start blog (1 post/month)
  Networking: attend BSides local, join OWASP chapter
Q3: First freelance engagement (small business web pentest)
  Study CRTO for red team specialization
Q4: Build client pipeline, 2-3 engagements
  Conference: submit talk to local BSides

The 15 hours per week for OSCP preparation is realistic -- it is aggressive enough to make meaningful progress but not so demanding that it requires quitting your day job. Five HTB machines per week at that pace means you are completing roughly one machine every weekday evening, which is a sustainable rhythm. The decision to start the blog in Q2 (concurrent with the OSCP exam, not before) is smart because Q1 study notes become your first blog content. The BSides talk submission in Q4 is ambitious for a first year but demonstrates the right mindset -- contributing to the community builds your reputation faster than any certification, and a BSides lightning talk (5-10 minutes) is achievable even for someone relatively new to the field. The CRTO addition for Q3 shows red team specialization thinking, which connects directly to the episode 50 material on adversary simulation.


Episode 70 covered building a pentesting practice -- certifications, lab environments, CTF competitions, freelancing, the engagement lifecycle, and turning everything from the first 70 episodes into a professional career. That was the capstone of the offensive arc.

Now we switch sides. For 70 episodes we found the vulnerabilities, exploited the misconfigurations, escalated the privileges, and demonstrated the impact. Starting today, we close the doors we spent all that time kicking open. And we start where every serious defense starts -- with the operating system underneath everything else.

Why Defaults Kill

A fresh Ubuntu Server install has SSH open on port 22 with password authentication enabled. Root can log in remotely. The firewall is not configured -- not "configured permissively," literally not running. Kernel parameters allow ICMP redirects, source routing, and IP forwarding. There are no file integrity monitors, no intrusion detection, no centralized logging. Every service runs with its default configuration, which was designed for ease of setup, not resistance to attack.

This is fine for a lab. For a production server, it is an invitation.

Everything we exploited in episodes 31 through 45 -- SUID binaries, writable cron jobs, kernel vulnerabilities, weak SSH credentials, misconfigured sudo rules, Docker group membership -- exists because someone deployed a default system and never hardened it. The privilege escalation techniques from episode 31 work precisely because the default Linux configuration trusts local users far more than it should. The lateral movement techniques from episode 34 work because default firewalls allow unrestricted outbound connections. The persistence mechanisms from episode 50 work because default file integrity monitoring is nonexistent.

Hardening is the process of reducing the attack surface to the minimum required for the system's function. Every service disabled, every port closed, every permission restricted -- these are doors closed to the attacker. A hardened system does not prevent all attacks (nothing does), but it eliminates the low-hanging fruit that makes the attacker's job trivially easy. The goal is to force the attacker into increasingly noisy, complex, and detectable attack paths -- or to make them give up and move to an easier target.

User and Access Hardening

The first layer of defense is controlling who can access the system and what they can do once they are on it. This is where we undo the generous defaults that make Linux accessible to beginners but vulnerable to attackers:

# 1. Disable root SSH login
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart sshd

# 2. Create a non-root admin user with sudo
adduser admin
usermod -aG sudo admin

# 3. Enforce strong passwords with PAM
apt install libpam-pwquality
# /etc/security/pwquality.conf:
# minlen = 14
# dcredit = -1  (at least 1 digit)
# ucredit = -1  (at least 1 uppercase)
# lcredit = -1  (at least 1 lowercase)
# ocredit = -1  (at least 1 special char)

# 4. Set password expiration
chage -M 90 -m 7 -W 14 admin
# Max age 90 days, min age 7 days, warn 14 days before expiry

# 5. Lock accounts after failed attempts
# /etc/pam.d/common-auth:
# auth required pam_tally2.so deny=5 unlock_time=900
# Lock after 5 failures, unlock after 15 minutes

# 6. Restrict su to wheel group
groupadd wheel
usermod -aG wheel admin
# /etc/pam.d/su:
# auth required pam_wheel.so

# 7. Remove unnecessary users and groups
# Review /etc/passwd -- disable login for service accounts
usermod -s /usr/sbin/nologin games
usermod -s /usr/sbin/nologin lp
usermod -s /usr/sbin/nologin mail

The PAM (Pluggable Authentication Modules) configuration at step 3 connects directly to what we discussed in episode 7 about password strength. A 14-character minimum with complexity requirements does not make passwords uncrackable, but it eliminates the bottom 90% of the password distribution -- the password123 and Summer2026! patterns that password spraying attacks (like the one in our episode 70 exercise solution) exploit first. The pam_tally2 lockout at step 5 adds a brute-force brake: after 5 failed attempts the account locks for 15 minutes, which makes online password attacks impractical while still allowing legitimate users who fat-finger their password to get back in.

Step 6 (restricting su to the wheel group) is one of those small configurations that makes a disproportionate difference. On a default system, any user can attempt su root and try passwords. With pam_wheel.so, only members of the wheel group can even attempt su -- everyone else gets rejected before the password prompt. This means a compromised low-privilege service account cannot attempt local password attacks against root, which eliminates an entire class of post-exploitation activity we covered in episode 31.

SSH Hardening

SSH is the front door. If you harden nothing else, harden SSH -- because it is the service most directly exposed to the internet and the one attackers probe first:

# /etc/ssh/sshd_config -- hardened configuration

# Authentication
PermitRootLogin no
PasswordAuthentication no          # key-only authentication
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
LoginGraceTime 30

# Protocol
Protocol 2
Port 2222                          # non-standard port (security through obscurity,
                                   # but reduces automated scanning noise by 99%)

# Restrictions
AllowUsers admin deployer          # whitelist specific users
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitEmptyPasswords no

# Ciphers (remove weak ones)
Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org

# Timeouts
ClientAliveInterval 300
ClientAliveCountMax 2

# Logging
LogLevel VERBOSE

Let me be direct about the port change. Moving SSH from 22 to 2222 is NOT real security -- it is security through obscurity, and we discussed in episode 4 why obscurity alone is insufficient. Having said that, the practical effect is dramatic: automated scanning bots (Shodan, Censys, and the thousands of SSH brute-force botnets) scan port 22 by default. Moving to a non-standard port eliminates roughly 99% of automated noise from your auth logs, which makes the remaining 1% (the targeted attacks that actually matter) much easier to spot. It is not a security control -- it is a signal-to-noise improvement for your monitoring.

The cipher configuration matters more than most administrators realize. The default SSH installation supports quit some legacy ciphers for backward compatibility, including algorithms that have known weaknesses. Restricting to aes256-gcm and chacha20-poly1305 (and the corresponding MACs and key exchange algorithms) ensures that every SSH session uses modern, audited cryptography -- the same principles we covered in episode 9 when discussing which cryptographic primitives to trust and which to avoid.

# Install fail2ban for brute force protection
apt install fail2ban

# /etc/fail2ban/jail.local:
# [sshd]
# enabled = true
# port = 2222
# maxretry = 3
# bantime = 3600
# findtime = 600

systemctl enable fail2ban
systemctl start fail2ban

# SSH with MFA (Google Authenticator)
apt install libpam-google-authenticator
# Run as user: google-authenticator
# /etc/pam.d/sshd: auth required pam_google_authenticator.so
# /etc/ssh/sshd_config: ChallengeResponseAuthentication yes
# Now SSH requires key + TOTP code

fail2ban watches your auth logs in real time and automatically blocks IP addresses that fail too many login attempts. Three failures within 10 minutes and the IP gets banned for an hour via a firewall rule. This is your automated response to the brute-force attacks we launched in episodes 7 and 17 -- now we are on the other side of it, and the tool is trivially effective. Combined with key-only authentication, fail2ban makes SSH brute-forcing not just difficult but physically impossible: there is no password to brute-force, and the IP gets banned after 3 failed key negotiations anyway.

The MFA addition (Google Authenticator) creates a second factor: even if an attacker steals your private key (from a compromised laptop, a backup, or a phishing attack), they still need the 6-digit TOTP code from your phone to complete the login. Key + TOTP is the gold standard for SSH authentication on internet-facing servers.

Filesystem Hardening

The filesystem is where attackers establish persistence, drop malware, and find the misconfigurations that enable privilege escalation. Hardening it means controlling what can execute, what has elevated permissions, and what changes without authorization:

# 1. Secure mount options in /etc/fstab
# /tmp with noexec, nosuid, nodev (prevents execution of uploaded malware)
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0
# /var/tmp similarly
tmpfs /var/tmp tmpfs defaults,noexec,nosuid,nodev 0 0
# /dev/shm (shared memory -- used in some privesc techniques)
tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0

# Remount immediately
mount -o remount,noexec,nosuid,nodev /tmp

# 2. Audit SUID/SGID binaries (from episode 31 -- now we defend)
find / -perm -4000 -type f 2>/dev/null > /var/log/suid-baseline.txt
# Remove SUID from anything that doesn't need it:
chmod u-s /usr/bin/newgrp
chmod u-s /usr/bin/chsh
chmod u-s /usr/bin/chfn

# 3. Set sticky bit on world-writable directories
find / -type d -perm -0002 ! -perm -1000 2>/dev/null
# Should return nothing -- all world-writable dirs need sticky bit

# 4. Restrict /etc/shadow permissions
chmod 640 /etc/shadow
chown root:shadow /etc/shadow

# 5. File integrity monitoring with AIDE
apt install aide
aideinit
# Creates a baseline database of all file hashes
# Run daily: aide --check
# Any modified system binary = investigation needed

The noexec mount option on /tmp deserves special emphasis. Remember episode 31 on Linux privilege escalation? One of the most common attack patterns is downloading a compiled exploit to /tmp (because /tmp is world-writable) and executing it. With noexec on /tmp, that exploit does not run -- the kernel refuses to execute any binary from that filesystem regardless of its permissions. The attacker can still write to /tmp, but the file sits there uselessly. This single mount option blocks a startling number of real-world Linux exploits that rely on /tmp as their staging directory ;-)

The SUID audit at step 2 is the defensive mirror of what we did offensively in episode 31. When we were attacking, we ran find / -perm -4000 to discover SUID binaries that could be abused for privilege escalation. Now we run the same command to build a baseline of which SUID binaries should exist. Anything not on that baseline is suspicious. And any SUID binary that does not genuinely need the setuid bit (like newgrp, chsh, chfn -- how often do your users really need to change their login shell via a setuid binary?) gets the bit removed. Fewer SUID binaries means fewer potential escalation paths.

AIDE (Advanced Intrusion Detection Environment) creates a cryptographic hash of every system file and stores it in a database. When you run aide --check daily (via cron), it compares the current state of the filesystem against the baseline and reports any changes. A modified /usr/bin/sudo binary that was not updated by apt is a VERY serious finding -- it likely means someone replaced the binary with a trojanized version. Without file integrity monitoring, you would never notice until the damage was done.

Kernel Hardening

The kernel is the lowest layer of the operating system and the final boundary between user processes and hardware. Default kernel parameters are tuned for functionality and compatibility, not security:

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

# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Disable source routing (prevents packet routing manipulation)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Disable ICMP redirects (prevents MITM via ICMP)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

# Enable SYN cookies (SYN flood protection)
net.ipv4.tcp_syncookies = 1

# Log martian packets (packets with impossible source addresses)
net.ipv4.conf.all.log_martians = 1

# Disable core dumps (prevent credential leakage via core files)
fs.suid_dumpable = 0

# ASLR (should be enabled by default, verify)
kernel.randomize_va_space = 2

# Restrict kernel pointer leakage
kernel.kptr_restrict = 2

# Restrict dmesg access to root
kernel.dmesg_restrict = 1

# Disable unprivileged BPF (prevents certain privesc techniques)
kernel.unprivileged_bpf_disabled = 1

# Apply immediately
sysctl --system

Every one of these parameters closes a specific attack vector we have discussed in this series. The ICMP redirect disable prevents the network-level MITM attacks from episode 29. The randomize_va_space = 2 ensures ASLR is active -- the memory randomization that makes the exploit development techniques from episodes 42 and 43 significantly harder (without ASLR, buffer overflow exploitation becomes almost trivial because the attacker knows exactly where their shellcode will land in memory). The kptr_restrict = 2 prevents unprivileged users from reading kernel pointer addresses via /proc/kallsyms, which removes one of the information leaks that kernel exploit developers rely on.

The kernel.unprivileged_bpf_disabled = 1 setting is newer and increasingly important. BPF (Berkeley Packet Filter) is a powerful kernel subsystem that allows programs to run sandboxed code inside the kernel itself. Several recent Linux privilege escalation CVEs have exploited bugs in the BPF verifier -- the component that is supposed to ensure BPF programs are safe. Disabling unprivileged BPF access means only root can load BPF programs, which eliminates an entire category of kernel-level privilege escalation.

Firewall Configuration

A firewall is only useful if it defaults to deny -- meaning everything is blocked unless explicitly allowed. The most common firewall misconfiguration is a default-allow policy with a few specific blocks, which is backwards and guarantees that new services are exposed the moment they start:

# nftables (modern replacement for iptables)

# /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # Allow established connections
        ct state established,related accept

        # Allow loopback
        iif lo accept

        # Allow SSH (hardened port)
        tcp dport 2222 accept

        # Allow HTTP/HTTPS (if web server)
        tcp dport { 80, 443 } accept

        # Allow ICMP ping (optional -- some prefer to drop)
        icmp type echo-request limit rate 5/second accept

        # Log and drop everything else
        log prefix "DROPPED: " drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
        # Consider restricting outbound too for high-security systems
    }
}

# Enable
systemctl enable nftables
nft -f /etc/nftables.conf

The policy drop on the input chain is the most important line in this entire configuration. It means that ANY traffic not matching an explicit allow rule is dropped and logged. A new service starts listening on port 8080? Blocked by default until you add a rule for it. An attacker scans your server with Nmap (episode 5)? Every port except 2222, 80, and 443 returns nothing -- not a "closed" response, just silence, which makes it harder for the attacker to determine whether the host is even alive.

The ct state established,related accept rule is what makes stateful firewalling work: it allows responses to connections YOUR server initiated (DNS lookups, package updates, API calls) without opening those ports for inbound connections. Without this rule, your server could not receive responses to its own outbound requests.

For high-security environments, consider restricting the output chain as well. A compromised server with unrestricted outbound access can exfiltrate data, connect to C2 infrastructure (episode 62), download additional tools, and pivot to other targets (episode 34). Restricting outbound to only the necessary destinations (DNS servers, package repositories, specific API endpoints) creates a significant obstacle for post-exploitation activity. It is more work to maintain, but for systems handling sensitive data it is absolutely worth the effort.

AppArmor and SELinux

Even with all the hardening above, a determined attacker who finds a vulnerability in one of your running services (a web server RCE, for example) can potentially leverage it to access files, networks, or processes that the compromised service should never touch. Mandatory Access Control (MAC) solves this by defining exactly what each process is allowed to do -- and blocking everything else, regardless of Unix file permissions:

# AppArmor (default on Ubuntu/Debian)
aa-status
# Shows which profiles are enforcing

# Create a profile for a service
aa-genprof /usr/sbin/nginx
# Run nginx normally while aa-genprof learns what it needs
# Review and enforce:
aa-enforce /etc/apparmor.d/usr.sbin.nginx

# SELinux (default on RHEL/CentOS/Fedora)
# Check status
getenforce
# Enforcing = blocking violations, Permissive = logging only

# List SELinux violations
ausearch -m avc -ts recent

# Set SELinux to enforcing
setenforce 1
# Make permanent: edit /etc/selinux/config -> SELINUX=enforcing

The difference between AppArmor and SELinux is primarily one of approach, not capability. AppArmor uses path-based rules -- "nginx can read files in /var/www/ and write to /var/log/nginx/ and nothing else." It is simpler to configure and understand, which is why Ubuntu and Debian ship with it. SELinux uses label-based rules -- every file, process, and port gets a security context label, and policies define which label combinations are allowed to interact. SELinux is more granular and more complex, which is why Red Hat ships with it and most administrators promptly set it to permissive mode (logging only, not enforcing).

Neither system is inherently better. What matters is that you USE one of them in enforcing mode. A compromised nginx process behind an enforcing AppArmor profile can read the web root and write logs -- and that is ALL it can do. It cannot read /etc/shadow, it cannot spawn a reverse shell to an external IP, it cannot write to /tmp and execute a privilege escalation exploit. The AppArmor policy confines the damage to the service's legitimate scope, which is exactly the containment principle we discussed in episode 53 when talking about security architecture and defense in depth.

The reality in most organizations is bleak: SELinux is set to permissive (or disabled entirely) because "something broke and we turned it off." That "something" was a legitimate access pattern that the default policy did not cover, and instead of writing a custom policy rule, the administrator disabled the entire MAC system. This is equivalent to removing your seatbelt because it was uncomfortable -- it works fine right up until the crash.

Automated Hardening

Manual hardening is error-prone and does not scale. For production environments with more than a handful of servers, automation is not just convenient -- it is mandatory:

# Lynis -- security auditing tool
apt install lynis
lynis audit system
# Produces a hardening score and specific recommendations
# Run monthly, track score improvement over time

# CIS Benchmark -- Center for Internet Security
# Download the CIS Ubuntu benchmark PDF
# Contains 300+ specific configuration checks with remediation
# Available at: cisecurity.org/benchmark/ubuntu_linux

# Ansible hardening playbook (automate everything)
ansible-galaxy install dev-sec.os-hardening
# Apply to all servers:
# ansible-playbook -i inventory hardening.yml

# The dev-sec hardening collection covers:
# - OS hardening (users, permissions, kernel)
# - SSH hardening (all sshd_config settings)
# - MySQL/PostgreSQL hardening
# - Nginx/Apache hardening

Lynis deserves your attention because it quantifies your hardening with a score (0-100) and tells you exactly what to fix. A fresh Ubuntu Server typically scores around 50-60. After applying everything in this episode, you should be above 80. Running Lynis monthly and tracking the score over time gives you a measurable security posture trend -- which is exactly what management wants when they ask "are we more secure than last quarter?"

The Ansible hardening playbooks from the dev-sec project are the automation approach to everything we have covered today. Instead of manually editing sshd_config, sysctl.conf, and nftables.conf on every server, you define the desired state in an Ansible role and apply it across your entire infrastructure in one command. This connects directly to episode 38 on Infrastructure as Code and episode 67 on DevSecOps -- hardening becomes part of your deployment pipeline, applied automatically to every new server, verified on every change. A server that drifts from the hardened baseline gets flagged and corrected automatically.

The combination of Lynis for auditing and Ansible for enforcement creates a feedback loop: Lynis finds what is wrong, you write Ansible tasks to fix it, you run Lynis again to verify, and Ansible ensures no server drifts back. This is how hardening scales from one server to a thousand without requiring a thousand manual configuration sessions.

The AI Slop Connection

AI-generated server setup guides are the opposite of everything in this episode. Every AI-generated "deploy to production" tutorial I have reviewed uses root for everything, enables password authentication on SSH, opens all ports in the firewall "for testing" (and never closes them), runs services as root because "it works," and skips every hardening step we have covered today.

The AI optimizes for "it works" not "it resists attack." A hardened server is harder to configure and harder to debug. The AI chooses the path of least resistance every time, and the path of least resistance is the default configuration -- the exact configuration that gives attackers everything they need. If you deploy an AI-generated server config to production, you are deploying a system that would fail every check in this episode. The sshd_config will have PermitRootLogin yes and PasswordAuthentication yes. The firewall will be either absent or set to policy accept. The kernel parameters will be at their default values. No AIDE, no fail2ban, no AppArmor, no sysctl hardening.

The fix is the same as it always is: use the AI output as a starting point if you must, then harden it manually using a checklist (CIS benchmarks, Lynis, or the steps in this episode). Better yet, use an Ansible hardening playbook that encodes all of these requirements and apply it to every server, regardless of how the initial configuration was generated. The machine-generated config gets you running. The hardening gets you secure. Never confuse the two.

Exercises

Exercise 1: Harden a fresh Ubuntu Server VM using every technique in this episode. Then run Lynis (lynis audit system) and document your hardening score. Aim for 80+ (out of 100). Document which checks you passed, which you failed, and why you chose to skip any specific recommendation (some may not apply to your use case). Save to ~/lab-notes/linux-hardening-audit.md.

Exercise 2: After hardening your VM, attempt the Linux privilege escalation techniques from Episode 31 against it. Try: (a) SUID binary abuse, (b) writable cron jobs, (c) sudo misconfiguration, (d) kernel exploit, (e) docker group. Document which attacks are now blocked and which (if any) still work. This proves the hardening is effective -- and any technique that still works tells you where your hardening has gaps. Save to ~/lab-notes/hardening-vs-privesc.md.

Exercise 3: Write an Ansible playbook that automates the hardening steps from this episode. The playbook should: (a) configure SSH (key-only, no root login, non-standard port), (b) install and configure fail2ban, (c) apply kernel sysctl hardening, (d) configure nftables firewall, (e) install and initialize AIDE. Test the playbook on a fresh VM and verify with Lynis that the automated hardening achieves the same score as your manual hardening from exercise 1. Save to ~/lab-tools/hardening-playbook.yml.


Bedankt en tot de volgende keer!

scipioHive account@scipio

Leave Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress to:

Written by

Does it matter who's right, or who's left?

Read more #stem posts


Best Posts From scipio

We have not curated any of scipio's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From scipio