Sécurité système

Travaux dirigés

TD : Installer un système sécurisé

Installer un système sécurisé sur base Debian

  • Chiffrement des disques
  • Partitionnement et montage adaptés
  • Durcissement noyau (sysctl)
  • Durcissement OpenSSH (PermitRootLogin no au minimum)
  • Filtrage Netfilter ( SSH – DHCP, DNS, HTTP[S])

Recommandations de l’ANSSI :

TD : Cloisonner et isoler

Intégrer une application avec des composants isolés

Isolation des deux services Python avec systemd

Tester l’application

  1. Récupérer (wget/scp…) les scripts api.py et crypto.py

  2. Installer les dépendances :

    apt install nginx uwsgi uwsgi-plugin-python3 python3-flask httpie netcat-openbsd
    
  3. Générer un secret et paramétrer les composants :

    openssl rand -out key.bin 16
    export KEY_PATH=key.bin
    export SOCKET_PATH=crypto.sock
    export FLASK_APP=api.py
    
  4. Lancer les services :

    python3 crypto.py & echo $! > crypto.pid
    flask run & echo $! > api.pid
    
  5. Tester les services :

    http --json POST :5000/hmac data="Hello World"
    

Préparer le déploiement

  1. Déployer les scripts dans un répertoire conforme au FHS (par exemple /opt/cryptosrv)
  2. Créer un groupe système (groupadd(8))
  3. Créer un compte de service (système, useradd(8)) pour chacun des deux scripts, en prenant garde à bien paramétrer les comptes (répertoire des scripts comme home et nologin(8) comme shell)
  4. Positionner le secret key.bin (paramétrage / configuration) dans un répertoire conforme au FHS et vérifier les permissions

Écrire le service systemd pour crypto.py

  1. Créer un service systemd pour lancer crypto.py (voir systemd.service(5) et systemd.exec(5))

    • le service doit utiliser son compte de service et son groupe
    • SOCKET_PATH et KEY_PATH doivent être paramétrées dans l’environnement
    • la socket devra être créée avec les bonnes permissions (umask) dans un répertoire géré par le service systemd sous /run
  2. Charger et lancer le service :

    systemctl daemon-reload
    systemctl start <xyz>.service
    
  3. Vérifier les permissions sur le répertoire sous /run et la socket

  4. Tester le service :

    echo "Hello world" | nc -U /run/.../xyz.sock | xxd
    

Écrire le service systemd pour api.py

  1. Créer un service systemd pour lancer api.py avec uWSGI (uwsgi-core(1) et documentation Flask)

    • le service doit utiliser son compte de service et les groupes nécessaires pour communiquer avec le service cryptographique et Nginx
    • SOCKET_PATH doit être paramétrée dans l’environnement
    • une socket, accessible à Nginx, doit être créée dans un répertoire géré par le service systemd sous /run
  2. Charger et lancer le service :

    systemctl daemon-reload
    systemctl start <xyz>.service
    
  3. Vérifier les permissions sur le répertoire sous /run et la socket

Configurer Nginx

  1. Configurer Nginx pour communiquer avec la socket uWSGI (voir documentation uWSGI)

    location / { try_files $uri @cryptosrv; }
    location @cryptosrv {
        include uwsgi_params;
        uwsgi_pass unix:/run/.../uwsgi.sock;
    }
    
  2. Redémarer Nginx et tester l’application :

    systemctl restart nginx.service
    http --json POST :/hmac data="Hello World"
    

Correction

Si vous avez obtenu une application opérationnelle, félicitations !

Sinon, pas de panique, voici des fichiers fonctionnels :

En complément, un Makefile avec les cibles suivantes : (nécessite évidemment make)

  • test-dependancies : installe python3-flask et httpie
  • test : teste l’application (ne nécessite pas les droits root)
  • install-dependancies : installe nginx uwsgi uwsgi-plugin-python3 python3-flask httpie et netcat-openbsd
  • install : déploie, configure et teste l’application

TD : Journaliser et centraliser

Ajouter des fonctionnalités de journalisation centralisée

  • Journaliser les requêtes et les opérations cryptographiques
  • Conserver 7 jours localement
  • Conserver 1 mois sur un serveur de centralisation

Travail à rendre pour ⅛ de la note finale du module

Modifier crypto.py pour journaliser

  1. Installer python3-systemd

  2. Importer les modules Python nécessaires :

    import logging
    from systemd import journal
    
  3. Configurer le logger racine (logging.getLogger()) pour le SYSLOG_IDENTIFIER='cryptopy' à partir du niveau logging.INFO

  4. Utiliser logging.info() pour journaliser proprement les messages à la place des print()

  5. Redémarrer le service et vérifier la journalisation :

    systemctl restart cryptopy.service
    journalctl -eu cryptopy.service
    

Modifier api.py pour journaliser

  1. Configurer de même app.logger pour écrire vers systemd avec le SYSLOG_IDENTIFIER='apipy'

  2. Journaliser la source (request.remote_addr) et le corps des requêtes ainsi que les HMAC correspondants générés

  3. Redémarrer le service et vérifier la journalisation :

    systemctl restart apipy.service
    journalctl -eu apipy.service
    

Configurer rsyslog

  1. Vérifier que les journaux de cryptopy et apipy remontent dans /var/log/messages via rsyslog.

  2. Configurer rsyslog avec un fichier /etc/rsyslog.d/20-cryptosrv.conf pour :

    • enregistrer localement (omfile) dans le répertoire /var/log/cryptosrv/ les journaux de cryptopy et apipy, avec programname puis la date (les 10 premiers caractères du format date-rfc3339) dans le nom du fichier
    • et les relayer en RELP (omrelp) vers un second serveur
    • relayer de même les facilities auth et authpriv
  3. Redémarrer rsyslog :

    systemctl restart rsyslog.service
    

Configurer le serveur de centralisation

Sur le second serveur :

  1. Configurer rsyslog avec un fichier /etc/rsyslog.d/10-central.conf pour :

    • écouter en RELP (imrelp)
    • enregistrer (omfile) les journaux reçus dans le répertoire /var/log/central/ avec le nom du serveur source et la date dans le nom du fichier.
  2. Redémarrer rsyslog :

    systemctl restart rsyslog.service
    
  3. Générer des journaux et vérifier leur centralisation

Rendu du TD

Avant le 01/06/2023 00:00:00 UTC+2 (heure de réception faisant foi) par courriel ou dépôt GitHub ou GitLab partagé à @reveliant :

  • codes sources modifiés de l’application Python :
    • /opt/cryptosrv/crypto.py
    • /opt/cryptosrv/api.py
  • configurations rsyslog des deux serveurs :
    • /etc/rsyslog.d/20-cryptosrv.conf
    • /etc/rsyslog.d/10-central.conf
  • exemples de message arrivés sur le serveur de centralisation :
    • /var/log/central/<serveur>-<YYYY-MM-DD>.log

Pour aller plus loin

  • Identifier les ressources sensibles et les surveiller avec auditd
  • Mettre en place une pile Elasticsearch pour indexer et faciliter la rechercher dans les journaux

Recommandations de l’ANSSI :