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.
On peut maintenant ping la db uniquement depuis le conteneur php, et pas nginx qui ne peut ping que le serveur php :
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 :
On observe les fichiers crées :
Puis on l'auto-signe :
On observe le fichier de signature :
En affichant les données, on voit bien que le certificat a été signé par nous-même :
www
4.1.2. Configuration de Nginx en HTTPS pour le virtualhost 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 :
On ouvre le port 443 du conteneur nginx dans le docker_compose.
Malheureusement, le navigateur trouve notre certificat pas terrible :
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.
www
4.2. Obtention d'un certificat Let's Encrypt pour le site Après avoir installé certbot sur le conteneur nginx, on lui fait certifier notre site :
On voit qu'il a lui même modifié la configuration de nginx :
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
.
- 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
- 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;
}
}
- 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
- 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)
- 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 :
On examine le certificat reçu avec l'outil OpenSSL, et plus particulièrement les champs indiquant la signature du CA :
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 :
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 :