Chapitre 1417 minIntermédiaire
Exercices corrigés de services Linux type E6 et E7 SISR
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- auditer une configuration de serveur web et la corriger ;
- traduire une matrice de flux en règles nftables et en comptes MariaDB ;
- analyser un incident dans les journaux et proposer des contre-mesures ;
- préparer une réalisation E6 et sa recette.
5 exercices corrigés
Ce chapitre rassemble des cas de synthèse sur les services Linux, au format des épreuves du BTS SIO option SISR : lire et corriger une configuration, traduire une matrice de flux et d'habilitations, analyser des journaux après un incident, préparer une réalisation et sa recette pour l'épreuve E6, mener une tâche de la phase 2. Chaque cas mobilise plusieurs chapitres du cours ; les réponses sont rédigées comme on les attend d'un candidat. À l'écrit E7 SISR, on ne te demande pas de taper des commandes de mémoire, mais de lire une configuration, de repérer ce qui est dangereux et de proposer une correction justifiée : c'est l'esprit des cas 1, 2 et 3.
Cas 1 : auditer un serveur web
Exercice 1 sur 5 La configuration du prestataire Réussi À revoir
Avant la reprise du site de suivi par l'équipe de Sorbier, le prestataire qui l'avait installé fournit cette configuration de srv-web.
server {
listen 80;
server_name suivi.sorbier-logistique.fr;
root /var/www/suivi;
autoindex on;
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Il précise aussi : « Les fichiers du site appartiennent à www-data. Le fichier /var/www/suivi/config.php contient la clé de l'API de srv-gestion. PHP affiche les erreurs pour faciliter le dépannage. Le dépôt Git est dans /var/www/suivi/.git. »
- Relève au moins six faiblesses de cette installation et, pour chacune, le risque concret.
- Propose le server block corrigé.
Voir la réponseMasquer la réponse de l'exercice 1
1. Les faiblesses.
| Faiblesse | Risque |
|---|---|
| Site en HTTP seulement | Données des clients (numéros de colis, adresses) lisibles et modifiables sur le trajet |
root /var/www/suivi (pas de dossier public) | config.php et tous les fichiers de l'application sont joignables par une adresse web |
autoindex on | La liste des fichiers de chaque dossier s'affiche : un visiteur découvre config.php, les sauvegardes oubliées, le dossier .git |
.git dans la racine, aucun refus des fichiers cachés | Téléchargement de tout le code source et de son historique, avec les secrets qui y ont été commités |
Pas de vérification de l'existence du script PHP (try_files $fastcgi_script_name =404) | Risque de faire exécuter comme du PHP un fichier qui n'en est pas |
Fichiers propriété de www-data | Une faille de l'application permet de réécrire le site (défiguration, ajout d'une porte dérobée) |
Pool PHP www partagé, sous www-data | Aucune isolation avec les autres applications du serveur |
| Erreurs PHP affichées | Chemins, requêtes, parfois identifiants exposés aux visiteurs |
| Clé d'API dans un fichier de la racine | Fuite de la clé, donc accès aux données de srv-gestion par l'API |
2. Le server block corrigé, avec l'application déplacée pour que seul public/ soit servi, la configuration et le dépôt Git hors de la racine, un pool dédié et HTTPS :
server {
listen 80;
listen [::]:80;
server_name suivi.sorbier-logistique.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name suivi.sorbier-logistique.fr;
ssl_certificate /etc/letsencrypt/live/suivi.sorbier-logistique.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/suivi.sorbier-logistique.fr/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
root /var/www/suivi/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm-suivi.sock;
}
location ~ /\. {
deny all;
}
}
Et hors de Nginx : fichiers propriété de root, lisibles seulement par le compte du pool pour config.php (placé dans /var/www/suivi, au-dessus de public) ; display_errors = Off et journal des erreurs ; dépôt Git déployé ailleurs ou supprimé du serveur ; clé d'API renouvelée, puisqu'elle a pu être lue (chapitres 2, 4 et 6).
Tu avais trouvé ?
Cas 2 : flux, comptes et pare-feu de srv-glpi
Exercice 2 sur 5 De la matrice aux règles Réussi À revoir
La DSI de Sorbier valide ce tableau des accès à srv-glpi (192.168.10.184).
| Qui | Depuis | Besoin |
|---|---|---|
| Salariés et agents d'inventaire | VLAN 10 192.168.10.64/26 | GLPI en HTTPS |
| Techniciens de l'entrepôt | VLAN 30 192.168.10.128/27 | GLPI en HTTPS |
| Équipe informatique | VLAN 99 192.168.10.208/28 | GLPI en HTTPS, SSH |
| Grafana | srv-journaux 192.168.10.180 | Lecture des tables glpi_tickets et glpi_itilcategories |
| Script de sauvegarde | srv-glpi lui-même | Sauvegarde complète de la base glpi |
- Pour chaque ligne, dis si le flux traverse le pare-feu pfSense.
- Écris la chaîne d'entrée nftables de
srv-glpi. - Écris les comptes MariaDB et leurs droits pour les deux dernières lignes. Le script de sauvegarde tourne en
rootsur le serveur.
Voir la réponseMasquer la réponse de l'exercice 2
1. Les VLAN 10, 30 et 99 sont d'autres réseaux que le VLAN 20 de srv-glpi : ces trois flux traversent pfSense, qui doit les autoriser (règles sur les interfaces des VLAN 10, 30 et 99). srv-journaux est dans le même VLAN 20 : son flux ne traverse pas pfSense, seul le pare-feu local le filtre. Le script de sauvegarde ne quitte pas la machine.
2.
chain entree {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif "lo" accept
icmp type echo-request accept
icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } accept
ip saddr { 192.168.10.64/26, 192.168.10.128/27, 192.168.10.208/28 } tcp dport { 80, 443 } accept
ip saddr 192.168.10.208/28 tcp dport 22 accept
ip saddr 192.168.10.180 tcp dport 3306 accept
limit rate 10/minute log prefix "nft-refus: "
}
Un ensemble écrit entre accolades directement dans la règle (ensemble anonyme) peut contenir des réseaux : nftables le gère sans déclaration préalable. Un ensemble nommé, comme @admin au chapitre 13, devient utile dès qu'il sert dans plusieurs règles.
3.
CREATE USER 'grafana_lecture'@'192.168.10.180' IDENTIFIED BY '…' REQUIRE SSL;
GRANT SELECT ON glpi.glpi_tickets TO 'grafana_lecture'@'192.168.10.180';
GRANT SELECT ON glpi.glpi_itilcategories TO 'grafana_lecture'@'192.168.10.180';
Le script de sauvegarde n'a pas besoin de compte : lancé en root sur le serveur, il se connecte au compte root@localhost de MariaDB par le socket Unix, sans mot de passe stocké nulle part (sudo mariadb-dump --single-transaction glpi). Côté serveur MariaDB : bind-address = 192.168.10.184 et require_secure_transport = ON pour que Grafana puisse se connecter en TLS (chapitre 5).
Tu avais trouvé ?
Cas 3 : analyser un incident dans les journaux
Exercice 3 sur 5 Une nuit agitée sur le site de suivi Réussi À revoir
Le lundi matin, Wazuh a levé plusieurs alertes pour srv-web1. Tu disposes de ces extraits (adresses d'Internet réservées à la documentation).
# Journal d'accès Nginx, transmis à srv-journaux
01:02:11 198.51.100.77 "GET /wp-login.php HTTP/1.1" 404
01:02:11 198.51.100.77 "GET /.env HTTP/1.1" 403
01:02:12 198.51.100.77 "GET /phpmyadmin/ HTTP/1.1" 404
… (1 240 requêtes de ce type en 6 minutes)
02:15:40 203.0.113.5 "POST /connexion.php HTTP/1.1" 200
… (3 800 requêtes POST sur /connexion.php entre 02:15 et 02:58, depuis 214 adresses différentes)
03:20:05 203.0.113.61 "GET /suivi.php?colis=<valeur contenant une apostrophe et des mots-clés SQL> HTTP/1.1" 500
# Journal d'erreurs PHP du pool suivi
03:20:05 PHP Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation …
- Identifie les trois activités et nomme-les.
- Pour chacune, dis si elle a pu réussir d'après ces traces, et ce qu'il faut vérifier.
- Propose des contre-mesures, en distinguant le serveur, l'application et l'architecture.
Voir la réponseMasquer la réponse de l'exercice 3
1. Les trois activités.
- 01:02 : un balayage automatisé (reconnaissance) : un robot teste en rafale des chemins connus d'applications vulnérables (WordPress, phpMyAdmin, fichiers
.env). - 02:15–02:58 : une attaque sur les mots de passe du formulaire de connexion, distribuée sur 214 adresses : force brute, ou bourrage d'identifiants (credential stuffing, essai de couples identifiant-mot de passe volés ailleurs).
- 03:20 : une tentative d'injection SQL : la valeur du paramètre
coliscontient de la syntaxe SQL, et l'application la recopie dans sa requête, puisque la base renvoie une erreur de syntaxe.
2. Réussite et vérifications.
- Balayage : réponses
404et403, rien de trouvé. Rien à faire, sinon vérifier qu'aucune requête de la série n'a reçu200. - Mots de passe : les réponses
200ne disent pas si la connexion a réussi (la page de connexion répond200même en cas d'échec). Il faut lire les journaux de l'application : y a-t-il eu des connexions réussies pendant la fenêtre, et depuis quelles adresses ? Si oui, réinitialiser les mots de passe concernés et prévenir les clients. - Injection : l'erreur
500et l'exception PDO prouvent que la requête est construite par concaténation : la faille existe, même si cette tentative a échoué. Chercher dans les journaux d'autres requêtes de la même adresse ou du même type ayant reçu200(une injection réussie ne produit pas d'erreur), et vérifier dans la base les droits du compte de l'application et les données lisibles par lui.
3. Contre-mesures.
| Niveau | Mesure |
|---|---|
| Application | Requêtes préparées pour toute valeur venue de l'utilisateur (cours PHP et MySQL) ; validation du format du numéro de colis ; limitation du nombre d'essais de connexion par compte, verrouillage temporaire, double authentification pour les comptes sensibles |
| Serveur | display_errors = Off (déjà le cas, l'erreur n'est que dans le journal) ; fail2ban sur les 404 en rafale ; limitation de débit dans Nginx (limit_req) sur /connexion.php ; compte de base de données aux droits minimaux |
| Architecture | Le serveur est en DMZ et ne joint srv-gestion que par l'API : vérifier les journaux de l'API sur la période ; un pare-feu applicatif (WAF) devant les répartiteurs filtrerait une partie de ces attaques ; la supervision Wazuh a joué son rôle et doit déclencher une procédure de gestion d'incident (cours Cybersécurité des infrastructures) |
Tu avais trouvé ?
Cas 4 : préparer une réalisation pour l'E6 SISR
Exercice 4 sur 5 Un intranet en HTTPS, hautement disponible Réussi À revoir
Pour ta seconde réalisation professionnelle, tu dois répondre au besoin suivant de Sorbier : « Publier pour les salariés un intranet (une application PHP avec sa base), accessible en HTTPS avec le compte Windows de chacun, qui reste disponible si un serveur tombe, et dont les incidents sont détectés. »
- Propose l'architecture (serveurs, adresses, services) en restant dans le plan d'adressage de Sorbier.
- Rattache chaque élément à une exigence de l'environnement technologique de l'E6 SISR.
- Rédige la liste des tests de la recette (au moins huit), avec le résultat attendu.
Voir la réponseMasquer la réponse de l'exercice 4
1. Architecture (dans le VLAN 21 APPLIS 192.168.21.0/24, passerelle 192.168.21.254) :
| Élément | Adresse | Rôle |
|---|---|---|
Adresse virtuelle intranet.ad.sorbier.example | 192.168.21.20 | Portée par le répartiteur actif (keepalived) |
srv-intra1 | 192.168.21.21 | HAProxy, keepalived (priorité 150), Nginx et PHP-FPM |
srv-intra2 | 192.168.21.22 | HAProxy, keepalived (priorité 130), Nginx et PHP-FPM |
| Base MariaDB | 192.168.21.23 | Base de l'intranet, sauvegardée chaque nuit vers srv-partages |
Le VLAN 20 192.168.10.176/28 n'a plus qu'une adresse libre, .187 : .182 à .186 sont pris par srv-collecte, le NAS, srv-glpi, srv-partages et le serveur de déploiement, .188 et .189 par les deux pare-feu en cluster (Pare-feu pfSense). Les quatre adresses vont donc dans le VLAN 21 APPLIS, ouvert pour les applications internes ; le pare-feu filtre les flux des postes vers ce VLAN comme vers le VLAN 20.
Pour limiter le nombre de machines, répartiteur et serveur web sont réunis sur chaque machine : HAProxy écoute en HTTPS sur l'adresse virtuelle et répartit vers les deux Nginx, qui écoutent sur un autre port (8080). L'authentification passe par l'annuaire en LDAPS ; le certificat vient de Sorbier-AC ; les journaux partent vers srv-journaux (rsyslog et agent Wazuh). La base reste un point unique de panne, à signaler comme limite (une réplication MariaDB la supprimerait, cours Haute disponibilité).
2. Rattachement à l'environnement exigé (liste complète) : service d'authentification (annuaire en LDAPS) ; SGBD (MariaDB) ; service rendu à l'utilisateur avec contraintes de sécurité et de haute disponibilité (l'intranet) ; accès sécurisé à un service interne (reverse proxy HTTPS) ; tolérance de panne (deux serveurs, adresse virtuelle VRRP) ; répartition de charge (HAProxy) ; supervision avec remontée d'alertes (Wazuh, et la supervision de l'adresse virtuelle) ; solution de sauvegarde (sauvegarde de la base) ; deux serveurs sur des systèmes différents, dont un libre (Debian ici, Windows Server pour l'annuaire).
3. Recette.
| N° | Test | Résultat attendu |
|---|---|---|
| 1 | curl -sI http://intranet.ad.sorbier.example | 301 vers HTTPS |
| 2 | Ouvrir l'intranet sur un poste du domaine | Cadenas, émetteur Sorbier-AC, aucun avertissement |
| 3 | Connexion avec jlefevre | Accès accordé ; refus avec un mauvais mot de passe |
| 4 | Connexion avec un compte désactivé dans l'annuaire | Refusée |
| 5 | Page de statistiques de HAProxy | Les deux serveurs web à l'état UP |
| 6 | Arrêter Nginx sur srv-intra1 | Le site répond toujours ; web1 passe DOWN dans les statistiques |
| 7 | Éteindre srv-intra1 | L'adresse virtuelle passe sur srv-intra2 (ip -br address) en quelques secondes ; le site répond |
| 8 | Rallumer srv-intra1 | L'adresse revient sur lui (préemption), aucune coupure visible |
| 9 | Capture sur le port 636 pendant une connexion | Échanges TLS, aucun mot de passe lisible |
| 10 | Cinq échecs de connexion SSH depuis une adresse de test | Alerte dans Wazuh, adresse bloquée par fail2ban |
| 11 | Restaurer la sauvegarde de la nuit dans une base de test | Base complète, l'intranet démarre sur la copie |
Chaque test est accompagné d'une capture ou d'une sortie de commande dans le dossier : c'est ce qui prouve, pendant l'entretien, que la solution fonctionne.
Tu avais trouvé ?
Cas 5 : une tâche de la phase 2 de l'E6
Exercice 5 sur 5 Un nouveau site en une heure Réussi À revoir
Pendant la phase 2 de l'épreuve E6, la commission te demande : « Le service commercial veut publier, sur srv-web, un site statique de présentation, www.sorbier-logistique.fr, en HTTPS, avec des journaux séparés transmis au serveur central. Le nom public pointe déjà vers l'adresse du pare-feu, qui redirige les ports 80 et 443 vers srv-web. » Décris les étapes dans l'ordre, avec les commandes, puis les vérifications que tu montres à la commission.
Voir la réponseMasquer la réponse de l'exercice 5
Étapes.
- Créer la racine et une page :
sudo mkdir -p /var/www/www/publicpuis une pageindex.html(fichiers propriété deroot). - Écrire
/etc/nginx/sites-available/www: un server block sur le port 80 avecserver_name www.sorbier-logistique.fr;,root /var/www/www/public;, des journauxwww.access.logetwww.error.log, et le refus des fichiers cachés (chapitre 2). - Activer :
sudo ln -s /etc/nginx/sites-available/www /etc/nginx/sites-enabled/,sudo nginx -t,sudo systemctl reload nginx. - Obtenir le certificat et passer en HTTPS :
sudo certbot --nginx -d www.sorbier-logistique.fr, qui ajoute HTTPS et la redirection ; ajouter ensuite HSTS avec une durée courte pendant la recette. - Vérifier que les nouveaux journaux sont transmis : avec le motif
/var/log/nginx/*.access.logde la configuration rsyslog (chapitre 12), rien à modifier ; ajouter le fichier au bloclocalfilede l'agent Wazuh s'il est déclaré fichier par fichier, puis redémarrer l'agent. - Mettre à jour la documentation : fichier de site, certificat, date d'expiration supervisée.
Vérifications montrées.
curl -sI http://www.sorbier-logistique.fr:301vers HTTPS.curl -sI https://www.sorbier-logistique.fr:200, en-têteStrict-Transport-Security.openssl s_client -connect www.sorbier-logistique.fr:443 -servername www.sorbier-logistique.fr </dev/null | openssl x509 -noout -subject -issuer -dates: certificat Let's Encrypt pour ce nom, dates valides.sudo certbot renew --dry-run: renouvellement simulé réussi.curl -sI https://suivi.sorbier-logistique.fr: le site existant fonctionne toujours (on n'a rien cassé).- Une requête sur le nouveau site, puis sa ligne retrouvée sur
srv-journaux.
Ce que la commission observe aussi : nginx -t avant chaque rechargement, une sauvegarde de la configuration avant modification, et la capacité à expliquer chaque directive.
Tu avais trouvé ?