TP6 : Sécurisation du service web public - Durionleponey/AdminII GitHub Wiki

[WIP] utilisation de gtp4o pour la relecture et la correction

Auteurs

  • De Henau Dudley
  • Gendebien Jonas
  • Clarembaux Robin
    Date de réalisation : 27/03/25

2. Sécurisation du serveur

  • Conteneurisation : Nginx, PHP, MariaDB dans Docker, isolation des services.
  • Ports exposés : uniquement le port 80 (HTTP).
  • Accès DB : uniquement en interne, pas d’exposition directe.
  • SSL manquant : trafic HTTP visible par tout le monde.

3. Sécurisation des données

3.1. Isolation de la base de données

  • Création d'un autre réseau dans le docker-compose pour isoler la DB.
  • Nginx est uniquement connecté au réseau principal (ex: monreseau).
  • PHP est connecté aux deux réseaux : monreseau (avec Nginx) et monreseau2 (avec MariaDB).
  • MariaDB n'est connecté qu'au réseau monreseau2.
  • Ainsi, Nginx peut communiquer avec PHP, PHP peut communiquer avec MariaDB, mais Nginx ne peut pas accéder directement à la base de données.
  • En cas de compromission de Nginx, cela limite l'attaque à PHP et empêche l'accès direct à MariaDB.

Procédure de validation de l'isolation

  1. Depuis le conteneur php, ping mariadb : docker exec -it php ping mariadb

  2. Depuis le conteneur web, ping mariadb : docker exec -it web ping mariadb

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

Validation de l’isolation des droits entre services

Objectif

S'assurer que le serveur web (Nginx) ne peut pas effectuer d’opérations dangereuses (ex: INSERT, DELETE, DROP) sur la base de données MariaDB.

Contexte

  • Un utilisateur wt-user@php est créé via un script au démarrage de MariaDB.
  • Il a uniquement le droit SELECT sur la base woodytoys.

Procédure de validation

  1. Depuis le conteneur php, se connecter à MariaDB avec wt-user : docker exec -it php mysql -u wt-user -p -h mariadb woodytoys

  2. Tester une requête SELECT (doit réussir) :

    SELECT * FROM products;

  3. Tester une requête INSERT (doit échouer) :

    INSERT INTO products (product_name, product_price) VALUES ('loooool', 999);

Résultat attendu

  • Les requêtes INSERT et DROP doivent échouer avec une erreur Access denied.
  • Seules les requêtes SELECT doivent être autorisées pour cet utilisateur depuis le conteneur php.

3.3. Backup de la DB

  • Le répertoire /var/lib/mysql du conteneur MariaDB contient toutes les données.
  • Ce dossier est monté via un bind mount, ce qui garantit que les données sont stockées sur l’hôte.

(volumes: - mariadb_data:/var/lib/mysql)

3.4. Logs de la DB

Docker logs -f mariadb

ou en interne

docker exec -it mariadb bash cd /var/log ls


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

sudo openssl req -x509 -nodes -days 365 \
  -newkey rsa:4096 \
  -keyout certificate/nginx-selfsigned.key \
  -out certificate/nginx-selfsigned.crt

{: .question }

Que pense votre navigateur du certificat utilisé ? Pourquoi ? Expliquez la problématique qui est ici mise en évidence.

Le navigateur affiche un avertissement indiquant que la connexion n’est pas sécurisée.
Cela est dû au fait que le certificat est auto-signé, c’est-à-dire qu’il n’a pas été émis par une autorité de certification reconnue.
La communication est bien chiffrée, mais le navigateur ne fait pas confiance à l'identité du serveur.


4.1.2. Configuration de Nginx en HTTPS pour le virtualhost www

Extrait du nginx.conf :

events {}

http {
    # 🔹 Définir le format de log personnalisé
    log_format log_per_virtualhost '[$host] $remote_addr [$time_local] $status '
                                   '"$request" $body_bytes_sent';

    # 🔹 Logs globaux (utilisé aussi dans les server blocks)
    access_log /dev/stdout log_per_virtualhost;
    error_log /dev/stderr;

    server {
    if ($host = www.crash.greenvault.eu) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        server_name www.crash.greenvault.eu;
        return 301 https://$host$request_uri;


}



    server {
        listen 443 ssl;
        server_name www.crash.greenvault.eu;
    ssl_certificate /etc/letsencrypt/live/www.crash.greenvault.eu/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.crash.greenvault.eu/privkey.pem; # managed by Certbot

        root /var/www/crash;
        index index.php index.html;

        access_log /dev/stdout log_per_virtualhost;

        location ~* \.php$ {
            fastcgi_pass php:9000;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }

}

HTTPS auto-signé en fonctionnement HTTPS auto-signé en fonctionnement


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

Certificat généré via certbot :

sudo certbot --nginx -d www.crash.greenvault.eu

{: .question }

1. Examinez les logs dans /var/log/letsencrypt/letsencrypt.log


2. Vérifiez votre configuration nginx : qu’est-ce qui a changé ?

Nginx a maintenant :

ssl_certificate /etc/letsencrypt/live/www.crash.greenvault.eu/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.crash.greenvault.eu/privkey.pem;

3. Vérifiez si votre site possède à présent un certificat signé par Let's Encrypt

HTTPS validé par Let's Encrypt HTTPS validé par Let's Encrypt HTTPS validé par Let's Encrypt


4. Examinez le certificat reçu avec OpenSSL

openssl x509 -in /etc/letsencrypt/live/www.crash.greenvault.eu/fullchain.pem -text -noout

5. Statut HTTPS du second Virtual Host : test.crash.greenvault.eu

Si ce vhost n’a pas de certificat, il retournera une erreur HTTPS.

  • Ajouter le vhost dans certbot :
sudo certbot --nginx -d test.crash.greenvault.eu