1ère mise en œuvre des scripts shell Mise en situation On désire réaliser un script qui alerte l’utilisateur à chaque fois qu’un port TCP/UDP est ouvert sur sa machine. L’alerte sera consignée dans un fichier journal qui rendra compte du/des port(s) ouvert(s) ainsi que la date et l’heure auxquelles il l’a/ont été. L’utilisateur pourra également être averti en direct par un moyen laissé à votre convenance (diffusion d’un son, envoi d’un mail…) La détection devra s’effectuer toutes les minutes. Travail demandé Affichage des informations sur les sockets réseau La commande ss de Linux permet d’afficher un certain nombre d’informations sur les sockets réseau comme : liste tous le sprocessus qui utilisent des sockets → ss -p liste toutes les connexions ssh actives → ss -o state established '( dport = :ssh or sport = :ssh )' … 🖮 Travail n° 1 : Commande ss Consulter la page de manuel de ss et expliquer ce que réalise la commande ss -tuan Les commandes “filtre” de Linux Dans cette partie, vous allez vous familiariser avec quelques unes des commandes généralistes de Linux qui permettent un traitement de données de type texte et ceci ligne par ligne. Ces commandes sont parfois appelées filtres car elles peuvent lire les lignes à traiter soit depuis un fichier soit depuis l’entrée standard (→ stdin) : elles peuvent donc être enchainées avec des tubes ou pipes (→ métacaractère | du shell). Ces commandes pourront être mises à profit pour l’élaboration du script final demandé. grep [OPTION…] PATTERN [FILE…] : permet de sélectionner les lignes d’un fichier texte ou de l’entrée standard ou bien encore d’un “here document” qui contiennent le motif (pattern) indiqué. Exemple : afficher les lignes du here document qui contiennent "ure" $ grep "ure" <<EOF > confiture > compote > bureau > chaise > EOF confiture bureau $ cut OPTION… [FILE…] : permet d’extraire des champs d’une ligne de texte Exemple : Extraire le prénom d’un enregistrement dont les champs sont séparés par ‘;’ $ echo "Manvussa ; Gérard ; 84 " | cut -d';' -f2 Gérard $ tr [options]… SET1 [SET2] : permet de copier l’entrée standard sur la sortie standard après avoir supprimé ou remplacé certains de ses caractères. Exemple : Remplacer tous les sauts de ligne d’un fichier par des espaces $ tr -s '\n' ' ' < file.txt uniq OPTION… [INPUT [OUTPUT]] : permet d’afficher sur la sortie les lignes de l’entrée en filtrant les lignes consécutives identiques Exemple : Supprimer les ligne consécutives identiques $ uniq <<EOF > foo > bar > bar > foo > foo > EOF foo bar foo # "foo" apparait 2 fois car dans le "here document" il y en a 3 au total mais seulement 2 sont consécutifs sort [OPTION]… [FILE]… : permet de trier les lignes qui lui sont fournies Exemple : Trier en sens inverse les prénoms fournis sort -r <<EOF > Alphonse > Benoit > Victor > Hugo > EOF Victor Hugo Benoit Alphonse $ tail [OPTION]… [FILE]… : Affiche les dernières lignes qui lui sont passées Exemple : Afficher les 3 dernières lignes du fichier /etc/passwd $ tail -n 3 /etc/passwd uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash wwwrun:x:30:8:WWW daemon apache:/var/lib/wwwrun:/bin/false claude:x:1000:100:Claude Defrance:/home/claude:/bin/bash $ 🖮 Travail n° 2 : Enchainement de commandes À partir des pages de manuel de Linux et des commandes présentées ci-dessus, élaborer la séquence de commandes à enchainer sur 1 seule ligne de commande (→ utilisation de pipes) pour réaliser chaque action définie ci-dessous : Afficher le nom complet de l’utilisateur de la session courante (→ variable d’environnement $USER) qui est indiqué dans le fichier /etc/passwd pour un utilisateur local ou bien dans le résultat de la commande getent passwd $USER. Afficher l’adresse IP de la passerelle par défaut en filtrant la sortie de la commande ip route Afficher sans doublons et par ordre croissant les adresses IP des serveurs NTP depuis lesquels l’heure du système a été synchronisée (← contenu du fichier /var/log/ntp) Afficher les 10 derniers évènements systèmes en rapport avec les port usb sachant que les évènements systèmes sont affichés avec la commande dmesg. On considèrera que les évènements liés à l’usb sont ceux où la ligne contient “] usb”. Le script d’alerte sur ouverture de ports UDP/TCP Avec la commande ss et les filtres vus précédemment, vous devez désormais être en mesure d’afficher les n° de ports ouverts sur votre machine. Pour détecter qu’un port a été ouvert, votre script doit déterminer les ports actuellement ouverts et comparer cette liste avec celle qui recense les ports déjà ouverts à la dernière exécution du script. L’astuce peut alors consister à enregistrer dans 2 fichiers les ports ouverts à un instant t et ceux ouverts à l’instant t + 1. La commande sdiff appliquée à ces 2 fichiers peut alors identifier les différences. Bien entendu, le 1ier appel au script déterminera la situation de référence et donc, seule la détermination des ports ouverts sera effectuée. On considèrera que l’absence du fichier de référence dans le répertoire de l’utilisateur suffira à identifier le 1ier appel au script. Pour signaler l’ouverture d’un port à l’utilisateur, l’alerte se résumera à un message affiché sur la console et sera journalisée dans un fichier de log avec indication de l’heure de détection et des nouveaux ports ouverts. 🖮 Travail n° 3 : Codage du script Déterminer la ligne de commande qui permet d’afficher par ordre croissant les ports tcp/udp actuellement ouverts sur la machine Débuter l’écriture du script de façon à ce qu’il réalise les actions suivantes : tester la présence du fichier ref_oports.log dans le répertoire de l’utilisateur s’il n’existe pas, le créer et le renseigner avec les ports actuellement ouverts s’il existe, se contenter d’afficher que le fichier existe déjà Compléter le script pour qu’il : détecte l’ouverture d’un nouveau port depuis le dernier appel journalise, le cas échéant, l’évènement dans le fichier oports_alert.log avec la date/heure de détection actualise le fichier ref_oports.log avec les ports actuellement ouverts pour créer une nouvelle référence en vue du prochain appel au script Exécution périodique du script Même s’il est opérationnel, votre script doit toujours être lancé manuellement afin de détecter les éventuels ports ouverts. Le lancer automatiquement à intervalle de temps régulier améliorerait grandement la détection d’intrusion. Sous Linux, il est possible de lancer une tâche périodiquement. Ceci est réalisé traditionnellement à l’aide de la commande crontab. Une manière plus moderne de procéder est de passer par des timers mis à disposition par le gestionnaire de système/services nommé systemd. La mise en œuvre est cependant plus délicate. Vous allez mettre en œuvre ces 2 méthodes pour exécuter périodiquement votre script. Utilisation de crontab 🖮 Travail n° 4 : Tâches planifiées avec crontab Lancer la commande crontab -e. Celle-ci doit normalement ouvrir un éditeur de texte à partir duquel vous allez devoir saisir une ligne qui permettra de configurer l’exécution périodique du script. À partir des informations données par exemple sur cette page, créer une tâche crontab de façon à ce que le script s’exécute toutes les minutes. Sauvegarder et quitter Vérifier avec la commande crontab -l que la demande d’exécution périodique de votre script a bien été prise en compte. Vérifier le fonctionnement du script en s’assurant : de la présence des fichiers créés/utilisés par votre script dans l’arborescence de fichiers du lancement d’une alerte lors de l’ouverture d’un port. Vous pouvez par exemple lancer le service apache2 pour constater l’ouverture des ports 80 (→ http) et 443 (→https) Désactiver l’exécution périodique du script soit en exécutant la commande crontab -r soit en relançant la commande crontab -e puis en effaçant la ligne de configuration précédemment saisie Utilisation des timers systemd 🖮 Travail n° 5 : Tâches planifiées avec les timers systemd Parcourir l’article Using systemd Timer Units to Schedule Jobs et adapter son contenu pour exécuter votre script toutes les minutes en utilisant un timer systemd. Pour aller plus loin … Modifier le script de façon à ce qu’il informe, dans le fichier journal : du nom du service associé au port dont l’ouverture a été détecté si celui-ci correspond à un service connu c’est-à-dire à un de ceux présents dans le fichier /etc/services. de l’adresse IP distante avec laquelle communique le port ouvert 🞄 🞄 🞄 🎯 Fiche de séquence SN1IR - Powershell