TP6 - DeumeniDerval/admin-2 GitHub Wiki

TP6 : Sécurisation du service web public

Noms des auteurs : Jérémie MUCHEMBLED

2. Sécurisation serveur

Documentez et faites le point ici sur l'état de sécurisation de votre serveur.

Le serveur a été sécurisé selon la procédure du TP3 :

Mettre à jour le système d’exploitation Modifier le port d’écoute SSH par défaut Créer un utilisateur avec des droits restreints Désactiver l’accès SSH de l’utilisateur root Configurer le pare-feu Installer Fail2ban et le configurer pour éviter les attaques brute-force sur SSH. Vérifier qu'aucun port n'est ouvert pour rien.

De plus, Docker a été mis à jour.

On utilise les dernières version stables pour nos images docker.

3. Sécurisation des données

3.1. Isolation de la base de données

On sépare les conteneurs dans deux réseaux différents dans le docker_compose : nginx et php dans la dmz, php et la db dans db_net : aucune communications directs entre nginx et la db.

Capture d'écran 2025-05-27 165451

On peut maintenant ping la db uniquement depuis le conteneur php, et pas nginx qui ne peut ping que le serveur php :

Capture d'écran 2025-05-27 170546

3.2. Configuration d'un utilisateur non privilégié

On créé un utilisateur non priviligiés dans la db :

CREATE USER 'wt-user'@'php' IDENTIFIED BY 'wt-pwd';
GRANT SELECT ON `woodytoys`.* TO 'wt-user'@'php';

On rajoute ces deux lignes au script en point d'entrée.

On crée un .env à coté du docker compose avec ces informations de connexion pour que php puisse les utiliser (on fournit ce fichier au conteneur php dans le docer-compose, comme pour la db).

Cela devrait empecher les serveur de modifier les données (INSERT, ALTER, DROP...).

3.3. Backup de la DB

On rajoute simplement un volume qui remplace le dossier où MariaDB stocke les données pour les rendre persistentes:

- ./db/data:/var/lib/MySQL

On peut également faire un backup manuellement :

sudo docker exec db mariadb-dump --all-databases -uroot -ppassword > ./db/backup/backup.sql

Le fichier créé par cette commande contient toutes les données de MariaDB.

3.4. Logs de la DB

Pour accéder aux logs de la DB, on fait simplement un docker logs db

4. Sécurisation des communications avec HTTPS

4.1. HTTPS via un certificat auto-signé

4.1.1. Génération du certificat auto-signé avec OpenSSL

On commence par créer un certificat pour notre site :

Capture d'écran 2025-05-27 221139

On observe les fichiers crées :

Capture d'écran 2025-05-27 221147

Puis on l'auto-signe :

Capture d'écran 2025-05-27 221315

On observe le fichier de signature :

Capture d'écran 2025-05-27 222052

En affichant les données, on voit bien que le certificat a été signé par nous-même :

Capture d'écran 2025-05-27 221407

4.1.2. Configuration de Nginx en HTTPS pour le virtualhost www

On met à jour la configuration de nginx pour rediriger les requêtes HTTP en HTTPS, et on indique notre certificat qu'on partagera avec le conteneur :

Capture d'écran 2025-05-27 222721

On ouvre le port 443 du conteneur nginx dans le docker_compose.

Malheureusement, le navigateur trouve notre certificat pas terrible :

Capture d'écran 2025-05-27 230000

En effet, il a été signé par nous-même, pour notre propre site, ce que nous avons tout intérêt à faire puisque personne ne veut d'un site non sécurisé. Il y a donc un gros conflit d'intérêt évident qui rend la crédibilité d'un tel certificat absolument nulle. D'où la méfiance du navigateur.

Capture d'écran 2025-05-27 230040

4.2. Obtention d'un certificat Let's Encrypt pour le site www

Après avoir installé certbot sur le conteneur nginx, on lui fait certifier notre site :

Capture d'écran 2025-05-27 234627

On voit qu'il a lui même modifié la configuration de nginx :

Capture d'écran 2025-05-27 234718

On remarque qu'il a recrée la même redirection, et qu'il a remplacé le certificat par celui qu'il a créé.

Examinons maintenant les logs dans le fichier /var/log/letsencrypt/letsencrypt.log. Nous cherchons :
- Les trois challenges ACME proposés par let's encrypt, et le token utilisé.
- La configuration nginx temporaire utilisée par certbot pour répondre au challenge.
- L'URL où se trouve le token sur votre serveur nginx.
- Le certificat reçu, de combien de parties il se compose.
- Où sont stockés les fichiers du certificat et de la clé privée générées par certbot.

  1. Les trois challenges ACME proposés par Let’s Encrypt
  • http-01
  • dns-01
  • tls-alpn-01

Tous utilisent le même token :

M6Rtv3-aqnAypvMLjJ4xZ3fwxo9sPFNn5S66YFamz4E
  1. Certbot a généré une configuration temporaire NGINX pour répondre au challenge http-01. Voici un extrait pertinent :
server {
    listen 80;
    server_name www.l1-5.ephec-ti.be;
    return 301 https://$host$request_uri;
    location = /.well-known/acme-challenge/M6Rtv3-aqnAypvMLjJ4xZ3fwxo9sPFNn5S66YFamz4E {
        default_type text/plain;
        return 200 M6Rtv3-aqnAypvMLjJ4xZ3fwxo9sPFNn5S66YFamz4E.HC0hx4ghtr2AnG2_XGAXZHBnPV979ZUXLCcLt9cwyqg;
    }
}
  1. L’URL pour accéder au token via le challenge http-01 est :
http://www.l1-5.ephec-ti.be/.well-known/acme-challenge/M6Rtv3-aqnAypvMLjJ4xZ3fwxo9sPFNn5S66YFamz4E
  1. Le certificat a bien été reçu. Il est composé de deux parties :

Le certificat pour le domaine (www.l1-5.ephec-ti.be)

Le certificat intermédiaire (chaîne de confiance jusqu'à l’autorité racine ISRG Root X1)

  1. Les fichiers de certificat et de clé privée sont stockés dans :
/etc/letsencrypt/live/www.l1-5.ephec-ti.be/

Avec les fichiers suivants :

cert.pem : le certificat du domaine

chain.pem : le certificat intermédiaire

fullchain.pem : cert.pem + chain.pem

privkey.pem : la clé privée

On a maintenant une connexion sécurisée :

Capture d'écran 2025-05-28 002829

On examine le certificat reçu avec l'outil OpenSSL, et plus particulièrement les champs indiquant la signature du CA :

Capture d'écran 2025-05-28 002655 Capture d'écran 2025-05-28 012537

Cette fois, les champs issuer et subject sont différents : le certificat n'est plus auto signé, on voit que le champ issuer indique letsencrypt

Cependant, la partie blog reste non sécurisée puisqu'on a demandé à certbot de s'occuper de la partie www uniquement. Il faudrait refaire la meme chose avec blog, ce qui créerait un deuxième certificat pour cette url.

4.3. Obtention manuelle d'un certificat pour le domaine

On execute cette commande :

certbot certonly --manual --preferred-challenges=dns --register-unsafely-without-email --agree-tos -d *.l1-5.ephec-ti.be -d l1-5.ephec-ti.be

Cette fois-ci la procédure de validation est manuelle : certbot nous donne des RR TXT à mettre dans notre zone DNS. On obtient un certificat valable pout tout les sous-domaines de l1-5, ainsi que pour le domaine lui-même :

Capture d'écran 2025-05-28 014914

On remplace les certificats spécifiques précédents par le nouveau sur tout les Virtual Hosts, et on observe une connexion sécurisée :

Capture d'écran 2025-05-28 042714