Linux Server Hardening
Exit

Lesson 1 of 13 · Fundamentals

Threat model and attack surface

30 min Debian 12 Versions Debian 12, Ubuntu 24.04, Rocky 9

Objective

Before hardening a server, know what you protect, against whom and where an attacker can get in. You will leave with a simple inventory method that you will reuse in every following lesson.

Key points

  • Hardening means removing from a system everything it does not need and locking down what remains. It is not installing "a security product".
  • A threat model answers three questions: which assets?, which threats?, which measures?
  • The attack surface is everything an attacker can reach: open ports, accounts, installed software, files with loose permissions, people.
  • Two principles guide the whole course: minimization (fewer things = fewer flaws) and defense in depth (several independent barriers).
  • You measure before and you measure after: without an initial inventory, you cannot prove that a server is safer.

1. Why harden? Three Moroccan situations

An SME in Casablanca sells online. Its website runs on a rented VPS. One morning, the home page shows a hacker's message. The cause: a web plugin that was never updated, and an SSH account admin with the password Admin2024.

A hospital in Fès has an appointment server. The server holds names, phone numbers and reasons for consultation. These are personal data under law 09-08, supervised by the CNDP. A leak makes the hospital legally liable.

A bank in Rabat is subject to strict rules: law 05-20 on cybersecurity and the directives of the DGSSI (Direction générale de la sécurité des systèmes d'information, the national information systems security authority). Auditors ask for evidence: written configuration, logs, audit report.

In all three cases, the question is not "can my server be attacked?" (yes, it will be) but "how much effort will the attacker need, and will I see the attack?".

2. Build a threat model in 15 minutes

Take a sheet of paper, or a simple text file, and fill in three columns.

Asset (what has value) Threat (what can happen) Measure (what I do)
Customer database Theft through SQL injection Limited SQL account, encrypted backups
SSH access Password brute force SSH keys, fail2ban
Showcase website Defacement Updates, read-only files
Server disk Failure or ransomware Off-server backup, tested

Then ask yourself "who?":

  • the bot that scans the whole Internet (the most common case: a few minutes after it goes online, a VPS already receives SSH attempts);
  • the cybercriminal looking for a server to encrypt for ransom;
  • the insider: a former employee, a contractor whose account was never closed;
  • human error: a backup file left in the web folder.

Hardening mainly protects against the first two and the last one. Against the insider, you also need procedures: close accounts when people leave, record actions (lesson 3.2).

3. Measure the attack surface

Here is the starting inventory, to run on every server. All these commands are read-only: they change nothing.

# Which system, which version? (the support lifetime depends on it)
cat /etc/os-release
uname -r                          # kernel version

# Who listens on the network? (TCP and UDP, with the program)
ss -tulpn
#  0.0.0.0:22   → open to everyone
#  127.0.0.1:3306 → local only (good for a database)

# Which accounts can open a session?
awk -F: '$7 !~ /(nologin|false)$/ {print $1, $7}' /etc/passwd

# Who can become root?
getent group sudo wheel           # sudo on Debian/Ubuntu, wheel on Rocky
ls /etc/sudoers.d/

# How many installed packages? (each package is a possible flaw)
dpkg -l | grep -c '^ii'           # Debian / Ubuntu
rpm -qa | wc -l                   # Rocky / RHEL

# Which services start with the machine?
systemctl list-unit-files --state=enabled

# Which programs run with their owner's rights (SUID)?
find / -xdev -type f -perm -4000 2>/dev/null

Keep these outputs in a dated folder, for example /root/inventaire/2026-10-19/. At the end of the course, you will run the same inventory again and compare.

4. The principles behind every decision

Minimization. A service that is not installed cannot be hacked. Before you "secure" an FTP server, ask yourself whether it is still useful.

Least privilege. Each account and each service has only the rights it needs. The web server has no reason to write to its own PHP files.

Defense in depth. Firewall, plus hardened SSH, plus fail2ban, plus logs: if one barrier falls, the next one holds.

Traceability. What is not logged never happened. Without logs, you cannot explain an incident to management, to the CNDP or to maCERT (the national CERT attached to the DGSSI).

Reversibility. Every change is written down, tested and reversible. You never harden a production server without an emergency console (the provider's VNC access, the VM console).

5. Security baselines: do not reinvent the wheel

You are not alone. Several organizations publish lists of recommendations:

  • ANSSI (the French agency): Recommandations de configuration d'un système GNU/Linux (configuration recommendations for a GNU/Linux system). Free, under the Licence Ouverte (open licence), in French. It ranks measures by level (minimal, intermediate, enhanced, high).
  • CIS Benchmarks (Center for Internet Security): very detailed guides for each distribution. Free to read, but their licence forbids copying them.
  • DGSSI: the national information systems security directive (DNSSI) sets rules for public administrations and critical infrastructures in Morocco.

This course follows the same spirit and teaches you to apply these measures, then to verify them with Lynis (lesson 4.1).

6. How the labs work

Labs run on your own virtual machine (never on your personal PC, never on a production server):

sudo ml demarrer hardening-1-1    # prepares the machine and shows the tasks
# … you work …
sudo ml verifier                  # checks each task

Some lessons modify sensitive files (SSH, firewall). So that you never lock yourself out, we will often work on a copy in /root/durcir/, which we test before applying it. Always keep the VM console open.

Depending on the version

Item Debian 12 Ubuntu 24.04 Rocky 9
Administrators group sudo sudo wheel
Bundled firewall none active (nftables installed) ufw (inactive) firewalld (active)
Mandatory access control AppArmor AppArmor SELinux
End of standard support mid-2026, then LTS until 2028 2029 (2034 with Ubuntu Pro) 2032

Common pitfalls

  • Hardening without an inventory: you will never know what you really improved, nor what you broke.
  • Copying a list of commands found online without understanding it: the best way to lock yourself out of SSH or break an application.
  • Forgetting "forgotten" accounts: a contractor who left with an active shell is an open door. The sync account (shell /bin/sync) is normal on Debian.
  • Believing a "brand new" VPS is safe: hosting providers' images often have SSH password authentication enabled.

Lab

You will start the inventory of your server:

  1. record the system and its version from /etc/os-release;
  2. close the account of a contractor who has left;
  3. list the accounts that can still open a session;
  4. write your first three-column threat model.

Quiz

  1. What are the three columns of a threat model?
  2. In the output of ss -tulpn, what is the difference between 0.0.0.0:3306 and 127.0.0.1:3306?
  3. Why is a service that is not installed safer than a well-configured service?
  4. Name two hardening baselines and their licence difference.
  5. Why do you need an emergency console before hardening SSH or the firewall?
Answers
  1. Asset (what has value), threat (what can happen), measure (what you do).
  2. 0.0.0.0:3306 accepts connections on all interfaces, so potentially from the Internet; 127.0.0.1:3306 only accepts local connections.
  3. Because it cannot contain any exploitable flaw: this is the minimization principle.
  4. The ANSSI guide (Licence Ouverte, reusable) and the CIS Benchmarks (free to read, reproduction forbidden).
  5. A configuration error can block every network connection: only the console (VNC, VM console) then lets you repair it.

Reference sources: ANSSI GNU/Linux guide (Licence Ouverte), Red Hat documentation, manual pages. Original MasterLinux text.

Practical exercises

To do on Debian 12

Do this lab on your own machine

The terminal is yours: a Linux VM (VirtualBox, VMware, Hyper-V, WSL…) or Docker/Podman. The ml tool prepares the exercise and checks your work; the lesson is validated here automatically.

Create a free account to get your personal command and have your labs checked automatically.

Create my account

Tasks

  1. Write to /root/inventaire/systeme.txt the system identifier and version, separated by a space, as they appear in /etc/os-release (fields ID and VERSION_ID), for example: debian 12
    Show a hintLoad the file with . /etc/os-release then echo "$ID $VERSION_ID" > /root/inventaire/systeme.txt
    Show the solution
    . /etc/os-release && echo "$ID $VERSION_ID" > /root/inventaire/systeme.txt

    Check : . /etc/os-release && grep -qx "$ID $VERSION_ID" /root/inventaire/systeme.txt

  2. The account ancien_presta belongs to a contractor who has left. Remove any login shell from it (shell /usr/sbin/nologin) and lock its password.
    Show a hintusermod -s /usr/sbin/nologin ancien_presta then usermod -L ancien_presta (or passwd -l)
    Show the solution
    usermod -s /usr/sbin/nologin -L ancien_presta

    Check : getent passwd ancien_presta | cut -d: -f7 | grep -qx /usr/sbin/nologin && getent shadow ancien_presta | cut -d: -f2 | grep -q '^!'

  3. Write to /root/inventaire/comptes-shell.txt the sorted list (sort) of accounts whose shell ends neither with nologin nor with false, one name per line.
    Show a hintawk -F: '$7 !~ /(nologin|false)$/ {print $1}' /etc/passwd | sort > … — do not be surprised to see root and sync.
    Show the solution
    awk -F: '$7 !~ /(nologin|false)$/ {print $1}' /etc/passwd | sort > /root/inventaire/comptes-shell.txt

    Check : test -s /root/inventaire/comptes-shell.txt && awk -F: '$7 !~ /(nologin|false)$/ {print $1}' /etc/passwd | sort | cmp -s - /root/inventaire/comptes-shell.txt

  4. Write a small threat model in /root/inventaire/menaces.txt: at least 3 lines in the format "asset ; threat ; measure" (exactly two semicolons per line).
    Show a hintExample line: customer database ; theft through SQL injection ; limited SQL accounts + encrypted backups
    Show the solution
    printf 'base clients ; vol par injection SQL ; compte SQL limité et sauvegardes chiffrées\nacces SSH ; force brute sur les mots de passe ; clés SSH et fail2ban\nsite web ; défiguration ; mises à jour et droits en lecture seule\n' > /root/inventaire/menaces.txt

    Check : test "$(grep -c '^[^;][^;]*;[^;][^;]*;[^;][^;]*$' /root/inventaire/menaces.txt)" -ge 3

Official references consulted: ANSSI — Recommandations de configuration d'un système GNU/Linux (guide ANSSI-BP-028, Licence Ouverte) : principes de minimisation et de défense en profondeur ; Red Hat Enterprise Linux 9 — Security hardening (chapitre d'introduction) ; Pages de manuel os-release(5), passwd(5), ss(8). Original MasterLinux text.