TP06 - bpatureau/admin-2-TP GitHub Wiki
TP6 : Sécurisation du service web public
Noms des auteurs : Bastien Patureau, Guillaume Ladrière, Maxime Bongartz Date de réalisation : 24/03/25
2. Sécurisation serveur
Documentez et faites le point ici sur l'état de sécurisation de votre serveur.
2.1 Firewall
Le firewall écoute uniquement sur les ports que nous allons utiliser :
49152/tcp ALLOW Anywhere
22/tcp ALLOW Anywhere
53/tcp ALLOW Anywhere
53/udp ALLOW Anywhere
443 ALLOW Anywhere
49152/tcp (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)
53/tcp (v6) ALLOW Anywhere (v6)
53/udp (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
Ainsi que le ports 49152 (pour s'y connecter)
2.2 docker
On vérifie le docker pour être sur qu'il contient bien les versions les plus récentes et on fait une mise a jour pour avoir les dernières versions stables.
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
debian-web latest 7c9130b569fc 21 hours ago 204MB
debian-php latest 941a799b6c68 21 hours ago 498MB
dns-woodytoys dnssec 7546e86a5136 45 hours ago 39.4MB
internetsystemsconsortium/bind9 9.18 795b6052e1d6 3 days ago 39.4MB
mariadb 11.1 6c187fecc416 6 months ago 405MB
3. Sécurisation des données
3.1. Isolation de la base de données
Ajout des deux réseau docker dmz et db_net dans le fichier docker compose :
networks:
dmz:
driver: bridge
db_net:
driver: bridge
Le server MariaDB est placé dans le réseau db_net.
mariadb:
container_name: db
image: mariadb:11.1
env_file:
- db/root.env
- db.env
volumes:
- ./db/sql/:/docker-entrypoint-initdb.d/ # MariaDB container automatically loads SQL script at startup
- ./db/my-resolve.cnf:/etc/mysql/conf.d/my-resolve.cnf
- ./db/data_db/:/var/lib/mysql/
networks:
- db_net
Le server nginx est placé dans le réseau dmz.
nginx:
container_name: web
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./html/:/var/www/html/
- ./certificate/letsencrypt:/etc/letsencrypt
networks:
- dmz
Et le server PHP est a la fois dans dmz et db_net.
php:
container_name: php
build: php
volumes:
- ./html/:/var/www/html/
env_file:
- db.env
networks:
- dmz
- db_net
- Etablissez une procédure de validation de l'isolation de la base de données.
- En étant connecté au container PHP, ping la DB et ping le server Nginx. Les 2 doivent réussir.
- Depuis le container Nginx, ping la DB, le ping doit raté.
3.2. Configuration d'un utilisateur non privilégié
Dans le fichier sql qui est lancé dans mariaDB, on ajoute un utilisateur. Cette utilisateur appelé "wt-user" n'aura pour droit que d'utiliser SELECT
sur la base de données woodytoys
.
CREATE USER 'wt-user'@'tp6_php_1' IDENTIFIED BY 'wt-pwd';
GRANT SELECT ON `woodytoys`.* TO 'wt-user'@'php';
Dans notre fichier products.php, on indique que l'utilisateur et son mot de passe sont dans les variables d'environement et cet utilisateur sera wt-user.
$dbname = getenv('MARIADB_DATABASE');
$dbhost = getenv('MARIADB_HOST');
$dbuser = getenv('MARIADB_USER');
$dbpass = getenv('MARIADB_PASSWORD');
- Proposez une procédure de validation du fait que le serveur web ne peut pas effectuer d'opération dangereuse sur la DB.
3.3. Backup de la DB
Les données extraitent de la DB sont stockées dans db/data_db
.
Notre container MariaDB possède un volume pour récupérer ces données.
volumes:
- ./db/sql/:/docker-entrypoint-initdb.d/
- ./db/my-resolve.cnf:/etc/mysql/conf.d/my-resolve.cnf
- ./db/data_db/:/var/lib/mysql/
3.4. Logs de la DB
Docker nous permet d'avoir accès aux logs de la DB via docker logs [nom du container]
.
docker logs db
2025-03-31 09:01:45+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.1.6+maria~ubu2204 started.
2025-03-31 09:01:45+00:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB
2025-03-31 09:01:45+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2025-03-31 09:01:45+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.1.6+maria~ubu2204 started.
2025-03-31 09:01:46+00:00 [Note] [Entrypoint]: MariaDB upgrade not required
error: Found option without preceding group in config file: /etc/mysql/conf.d/my-resolve.cnf at line: 1
2025-03-31 9:01:46 0 [Note] Starting MariaDB 11.1.6-MariaDB-ubu2204 source revision 80abd847daf736cf8e57e83241c2e6fed74b4ed3 server_uid 72+4ASMvYxproTQgRqIDplDA1XA= as process 1
2025-03-31 9:01:46 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2025-03-31 9:01:46 0 [Note] InnoDB: Number of transaction pools: 1
2025-03-31 9:01:46 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
2025-03-31 9:01:46 0 [Note] mariadbd: O_TMPFILE is not supported on /tmp (disabling future attempts)
2025-03-31 9:01:46 0 [Note] InnoDB: Using liburing
2025-03-31 9:01:46 0 [Note] InnoDB: Initializing buffer pool, total size = 128.000MiB, chunk size = 2.000MiB
2025-03-31 9:01:46 0 [Note] InnoDB: Completed initialization of buffer pool
2025-03-31 9:01:46 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes)
2025-03-31 9:01:46 0 [Note] InnoDB: End of log at LSN=52404
2025-03-31 9:01:46 0 [Note] InnoDB: Opened 3 undo tablespaces
2025-03-31 9:01:46 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active.
2025-03-31 9:01:46 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ...
2025-03-31 9:01:46 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB.
2025-03-31 9:01:46 0 [Note] InnoDB: log sequence number 52404; transaction id 26
2025-03-31 9:01:46 0 [Note] Plugin 'FEEDBACK' is disabled.
2025-03-31 9:01:46 0 [Note] Plugin 'wsrep-provider' is disabled.
2025-03-31 9:01:46 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2025-03-31 9:01:46 0 [Note] Server socket created on IP: '0.0.0.0'.
2025-03-31 9:01:46 0 [Note] Server socket created on IP: '::'.
2025-03-31 9:01:46 0 [Note] InnoDB: Buffer pool(s) load completed at 250331 9:01:46
2025-03-31 9:01:46 0 [Note] mariadbd: Event Scheduler: Loaded 0 events
2025-03-31 9:01:46 0 [Note] mariadbd: ready for connections.
Version: '11.1.6-MariaDB-ubu2204' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
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
En suivant les étapes de création, on arrive à ce certificat auto-signé.
bastien@vps-ba173cd9:~/admin2/tp6$ openssl x509 -noout -text -in certificate/nginx-selfsigned.crt
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
7e:b0:6d:0b:e8:24:b5:94:49:8f:9c:42:b6:b2:a9:fd:5e:9a:ae:00
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = BE, ST = Namur, L = Gembloux, O = Ephec, OU = IT, CN = ns.l1-2.ephec-ti.be., emailAddress = [email protected]
Validity
Not Before: Mar 23 23:00:23 2025 GMT
Not After : Mar 23 23:00:23 2026 GMT
Subject: C = BE, ST = Namur, L = Gembloux, O = Ephec, OU = IT, CN = ns.l1-2.ephec-ti.be., emailAddress = [email protected]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:b6:6a:95:3c:dd:41:84:19:92:d0:17:25:6c:0e:
f5:ae:32:65:c6:81:9e:bd:4d:b2:83:23:91:40:f6:
{: .question }
Que pense votre navigateur du certificat utilisé ? Pourquoi ? Expliquez la problématique qui est ici mise en évidence.
Le navigateur considérait le certificat comme invalide. Il n'y a aucune sécurité dans le fait d'avoir un certificat signé par soi-même. Cela ne prouve en rien la légitimité du site puisque n'importe qui peut le faire.
www
4.1.2. Configuration de Nginx en HTTPS pour le virtualhost Afin de configurer le https en nginx, il a fallu mettre en place une redirection du trafic du port 80 au port 443.
server {
listen 80;
server_name www.l1-2.ephec-ti.be;
return 301 https://www.l1-2.ephec-ti.be$request_uri;
}
Réaliser le virtualhosting pour le port 443.
server {
listen 443 ssl;
server_name www.l1-2.ephec-ti.be;
index index.html;
root /var/www/html/www/;
location ~ \.php$ {
fastcgi_pass php:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Et indiquer l'emplacement des certificats
http {
# Format de log personnalisé incluant le virtual host
log_format log_per_virtualhost '[$host] $remote_addr [$time_local] $status '
'"$request" $body_bytes_sent';
ssl_certificate /etc/letsencrypt/live/l1-2.ephec-ti.be/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/l1-2.ephec-ti.be/privkey.pem;
Notre site est ainsi sécurisé via HTTPS.
www
4.2. Obtention d'un certificat Let's Encrypt pour le site On installe automatiquement certbot dans le server nginx via son Dockerfile.
FROM nginx
RUN apt-get update && apt-get install certbot python3-certbot-nginx -y
COPY nginx.conf /etc/nginx/nginx.conf
COPY html /var/www/html
EXPOSE 80 443
Le server Nginx possède un volume pour les certificat généré.
volumes:
- ./html/:/var/www/html/
- ./certificate/letsencrypt:/etc/letsencrypt
4.3. Obtention manuelle d'un certificat pour le domaine
Si vous avez réalisé l'obtention d'un certificat wildcard, documentez la procédure et prouvez qu'elle fonctionne sur votre domaine (par ex. via des screenshots).