Écrire des Scripts Shell Sécurisés
Mise à jour :
Beaucoup d’administrateurs systèmes sous-estiment les risques liés aux scripts Bash mal codés. Un script qui paraît inoffensif, comme la création de répertoires, peut en réalité exposer votre système à des attaques sérieuses s’il n’est pas écrit correctement. Les failles les plus courantes, comme l’injection de commandes, les permissions mal gérées ou les erreurs de gestion des variables, peuvent être exploitées par des utilisateurs malveillants pour accéder à des fichiers sensibles, modifier des configurations système ou causer des interruptions de service.
Présentation du script de base non sécurisé
Pour étayer ce guide, nous allons prendre un script Bash simple qui demande à l’utilisateur un fichier à supprimer, puis le supprime.
A priori, il est inoffensif, mais il présente plusieurs failles de sécurité importantes qui pourraient être exploitées par une personne malveillante pour endommager le système ou accéder à des données sensibles.
Problèmes identifiés :
- Pas de validation de l’entrée utilisateur : Le script supprime n’importe quel fichier sans vérifier si le fichier existe ou si le nom de fichier est valide.
- Variable non protégée : Le nom de fichier n’est pas entouré de guillemets, ce qui pourrait entraîner une mauvaise interprétation des noms de fichiers avec des espaces ou des caractères spéciaux.
- Pas de gestion des erreurs : Si la commande rm échoue, il n’y a aucune vérification ou gestion de l’erreur.
- Absence de chemins absolus : Le script utilise rm sans spécifier un chemin absolu, ce qui pourrait être détourné en modifiant la variable d’environnement PATH.
- Permissions non contrôlées : Le script peut être exécuté par n’importe qui, sans restrictions.
Shebang explicite
L’une des premières bonne pratique pour éviter des erreurs lors du lancement d’un script Shell consiste à définir clairement l’interpréteur que le script doit utiliser. Cela est fait à travers la ligne qu’on appelle shebang, qui se trouve au début de script et spécifie quel shell doit être utilisé pour l’exécuter.
Pourquoi utiliser un shebang explicite ?
Sans shebang, un script pourrait être exécuté par un shell par défaut non
prévu, ce qui pourrait mener à des comportements inattendus. Par exemple, si un
administrateur écrit un script en pensant qu’il sera toujours exécuté avec
bash mais qu’il est lancé avec un autre shell (comme sh ou dash),
des erreurs peuvent survenir. En ajoutant un shebang explicite tel que
#!/bin/bash
, nous nous assurons que le bon interpréteur est utilisé,
indépendamment des paramètres de l’utilisateur ou de son système.
Exemples de lignes shebang :
#!/bin/bash
: Spécifie que le script doit être exécuté avec Bash.#!/bin/sh
: Utilise le shell POSIX par défaut, souvent utilisé pour des scripts plus simples et portables.
Utiliser des chemins absolus pour les commandes
Le chemin absolu est une autre bonne pratique de sécurité qui garantit que les commandes exécutées dans votre script proviennent du bon répertoire système et non d’une version potentiellement malveillante.
Pourquoi utiliser des chemins absolus ?
Si vous utilisez simplement des commandes comme rm
, ls
ou cp
, le système
peut rechercher ces commandes dans les répertoires définis par la variable
d’environnement PATH
. Un utilisateur malveillant pourrait modifier cette
variable pour exécuter un programme différent avec le même nom que la commande.
Pour éviter cela, il est préférable d’utiliser des chemins absolus comme
/bin/rm
ou /usr/bin/ls
, assurant ainsi que la version officielle de la
commande est utilisée.
Exemple d’amélioration :
Validation et nettoyage de l’entrée utilisateur
Lorsque vous écrivez des scripts shell, il est essentiel de valider et nettoyer toutes les entrées utilisateur. En effet, ne jamais faire confiance aux données saisies par l’utilisateur est une règle de base en matière de sécurité.
Pourquoi valider l’entrée utilisateur ?
Lorsque vous demandez à un utilisateur de fournir des informations, comme le nom d’un fichier, vous ne pouvez pas être certain qu’il fournira des données valides. Un utilisateur malveillant pourrait par exemple entrer un chemin vers un fichier sensible ou pire, inclure des caractères spéciaux permettant une injection de commandes.
Prenons l’exemple d’un script qui demande le nom d’un fichier à supprimer. Si
l’utilisateur entre une commande malveillante au lieu d’un nom de fichier, comme
filename="; rm -rf /"
, sans validation, le script pourrait exécuter cette
commande dangereuse.
Exemple d’amélioration :
Pour éviter cela, nous devons vérifier que le fichier existe, et s’assurer que l’utilisateur a fourni une entrée correcte avant d’exécuter toute commande. Voici une méthode pour valider un nom de fichier et s’assurer qu’il existe :
Dans cet exemple, la condition [[ ! -e "$filename" ]]
vérifie si le fichier
existe. Si ce n’est pas le cas, le script affiche un message d’erreur et
s’arrête. Cela permet d’éviter que le script ne tente de supprimer un fichier
inexistant ou pire, que l’utilisateur exploite cette faiblesse pour exécuter des
commandes dangereuses.
Nettoyage de l’entrée utilisateur
Même avec une validation en place, il est également recommandé de nettoyer les
variables contenant des données saisies par l’utilisateur. Cela consiste à
supprimer les caractères spéciaux qui pourraient poser problème. Par exemple, on
peut utiliser sed
pour filtrer les caractères non autorisés :
Ce code supprime tous les caractères autres que des lettres, chiffres, points, tirets et tirets bas du nom de fichier. Cela réduit les risques que des caractères dangereux soient injectés dans la commande.
Activer les options de sécurité du shell
Une autre bonne pratique pour sécuriser vos scripts Bash consiste à activer
les options de sécurité du shell. Ces options permettent d’améliorer le
comportement du script en cas d’erreur et de renforcer sa robustesse. Il existe
trois principales options que je vais vous présenter ici : set -e
, set -u
,
et set -o pipefail
. Ensemble, elles permettent d’éviter de nombreuses erreurs
courantes pouvant conduire à des failles de sécurité.
set -e
: Arrêter le script en cas d’erreur
L’option set -e
permet d’arrêter l’exécution du script dès qu’une commande
retourne un code d’erreur non nul. Sans cette option, le script continue
d’exécuter les commandes même après une erreur, ce qui peut conduire à des
comportements imprévus et potentiellement dangereux.
Exemple sans set -e
:
Même si le fichier n’existe pas, le script affichera le message “Fichier
supprimé”, ce qui peut prêter à confusion. En activant set -e
, le script
s’arrête immédiatement après l’échec de la commande rm
.
set -u
: Interdire l’utilisation de variables non définies
L’option set -u
force le script à s’arrêter si une variable utilisée n’est pas
définie. Cela évite des erreurs liées à l’utilisation de variables non
initialisées qui pourraient contenir des valeurs inattendues.
Exemple sans set -u
:
Si filename
n’est pas défini, le script affichera une ligne vide ou pourrait
même causer des problèmes plus graves selon le contexte. En activant set -u
,
vous vous assurez que toute variable non définie provoquera un arrêt immédiat du
script.
set -o pipefail
: Gérer correctement les erreurs dans les pipelines
Dans les scripts Bash, il est fréquent d’utiliser des pipelines pour
enchaîner plusieurs commandes. Par défaut, le shell ne détecte qu’une erreur
dans la dernière commande du pipeline, ignorant les éventuelles erreurs dans les
commandes précédentes. L’option set -o pipefail
garantit que le script
s’arrête si n’importe quelle commande d’un pipeline échoue et pas seulement
la dernière.
Exemple sans set -o pipefail
:
Même si la commande cat
échoue parce que le fichier n’existe pas, le script
continuera d’exécuter grep
et affichera “Pipeline terminé”. En activant set -o pipefail
, le script détectera cette erreur et s’arrêtera.
Exemple d’utilisation combinée
Ces trois options peuvent être activées en une seule ligne pour assurer une exécution sécurisée et contrôlée de votre script :
Avec cette ligne, vous vous assurez que :
- Le script s’arrête en cas d’erreur (
set -e
). - Aucune variable non définie n’est utilisée (
set -u
). - Les erreurs dans les pipelines sont correctement gérées (
set -o pipefail
).
Limiter les permissions des fichiers
La gestion des permissions est une bonne pratique dans la sécurisation de vos scripts Bash. Les permissions définissent qui peut lire, modifier ou exécuter un fichier, et si elles ne sont pas configurées correctement, elles peuvent permettre à des utilisateurs non autorisés d’exécuter des actions nuisibles.
Pourquoi est-il important de limiter les permissions ?
Si un script Bash est exécuté avec des permissions trop larges, il peut être
utilisé ou modifié par n’importe quel utilisateur sur le système. Par exemple,
un script avec des permissions d’écriture pour tous les utilisateurs (chmod 777
) pourrait être modifié par un utilisateur malveillant pour inclure du code
nuisible. Même des scripts inoffensifs peuvent devenir dangereux s’ils sont
modifiés sans précaution.
En limitant les permissions d’exécution aux seuls utilisateurs autorisés, vous réduisez considérablement les risques d’abus ou de modification non intentionnelle de vos scripts.
Comment configurer les permissions correctement ?
L’utilisation de la commande chmod
permet de définir les permissions sur
les fichiers. Voici les permissions de base que vous devriez appliquer à vos
scripts :
-
chmod 700
: Cette commande donne l’accès complet (lecture, écriture, exécution) uniquement au propriétaire du fichier. Aucun autre utilisateur ne peut lire, modifier ou exécuter le script.- Exemple :
Avec ces permissions, seul l’utilisateur propriétaire du fichier pourra exécuter le script, ce qui garantit que des utilisateurs non autorisés ne pourront pas le modifier ou l’exécuter.
-
Vérification des permissions avant l’exécution : En plus de configurer les permissions du script lui-même, il est judicieux de vérifier que le fichier sur lequel le script travaille a les bonnes permissions. Par exemple, si le script doit manipuler des fichiers, il peut être utile de vérifier si vous avez les droits d’écriture avant d’exécuter une commande
rm
oumv
.- Exemple de vérification des permissions de fichier :
Ce code vérifie si le fichier est modifiable par l’utilisateur exécutant le script. Si ce n’est pas le cas, le script s’arrête avec un message d’erreur.
Exemple d’amélioration :
Dans un script sécurisé, vous devez :
- Utiliser
chmod 700
pour restreindre les permissions aux seuls utilisateurs autorisés. - Vérifier les permissions des fichiers manipulés pour vous assurer que seules les personnes disposant des droits adéquats peuvent les modifier.
Voici un exemple de script qui applique ces principes :
Dans ce script, nous avons restreint l’accès au fichier à son propriétaire avec
chmod 700
. Nous avons également ajouté une vérification des permissions de
fichier pour s’assurer que l’utilisateur dispose bien des droits d’écriture
sur le fichier avant de tenter de le supprimer.
Éviter le stockage d’informations sensibles
Lorsqu’il s’agit de sécurité dans les scripts Bash, une erreur fréquente est d’inclure des informations sensibles directement dans le script. Les mots de passe, les clés API, ou tout autre type d’information confidentielle ne doivent jamais être codés en dur dans le script. En effet, si le script est partagé, versionné ou mal protégé, ces informations peuvent facilement être compromises.
Pourquoi éviter le stockage des informations sensibles ?
Le fait d’inclure des informations sensibles directement dans un script pose un risque majeur pour la sécurité. Si un utilisateur non autorisé accède au script, il pourrait obtenir des informations comme des mots de passe, des identifiants d’accès à des services, ou des clés API qui pourraient être utilisés pour compromettre l’intégrité de votre système ou d’autres services associés.
Par exemple, un script qui inclut un mot de passe en clair pourrait être consulté par n’importe quel utilisateur ayant accès au fichier ou pire, être accidentellement envoyé dans un dépôt Git public.
Exemple d’un script non sécurisé :
Ici, le mot de passe de la base de données est visible en clair. Si ce script est partagé ou s’il est exécuté par un autre utilisateur, le mot de passe est immédiatement compromis.
Alternatives pour sécuriser les informations sensibles
Il existe plusieurs méthodes pour éviter de stocker des informations sensibles directement dans un script. Voici quelques-unes des meilleures pratiques :
Utiliser des variables d’environnement
Au lieu de coder en dur les informations sensibles dans le script, vous pouvez utiliser des variables d’environnement. Cela permet de conserver les données sensibles en dehors du script et d’y accéder de manière sécurisée.
Exemple avec variables d’environnement :
Dans cet exemple, DB_PASSWORD
n’est pas défini dans le script lui-même, mais
provient d’une variable d’environnement qui peut être définie de manière
sécurisée avant l’exécution du script. Vous pouvez définir cette variable
directement dans le terminal :
Ensuite, lorsque vous exécutez le script, il utilisera la valeur de la variable d’environnement. Cela garantit que le mot de passe ne figure pas dans le script et n’est visible que temporairement dans l’environnement où il est défini.
Utiliser un fichier de configuration sécurisé
Une autre méthode consiste à stocker les informations sensibles dans un
fichier de configuration sécurisé qui n’est pas accessible à tous les
utilisateurs. Ce fichier peut être lu par le script, mais il doit avoir des
permissions strictes (comme chmod 600
pour empêcher toute lecture par d’autres
utilisateurs).
Exemple d’utilisation d’un fichier de configuration :
Le fichier fichier_config.conf
contiendra les informations sensibles et aura
des permissions restreintes pour empêcher tout accès non autorisé :
Utiliser un gestionnaire de secrets
Pour les environnements plus complexes, il est recommandé d’utiliser un gestionnaire de secrets (comme HashiCorp Vault, Sops, ou Infisical) pour stocker et gérer les informations sensibles. Ces outils offrent des fonctionnalités de gestion sécurisée des secrets, notamment le chiffrement et la rotation automatique des clés et mots de passe.
Le script peut alors récupérer les informations sensibles en les demandant dynamiquement au gestionnaire de secrets, plutôt que de les stocker localement ou dans le script lui-même.
Exemple avec un gestionnaire de secrets (pseudocode) :
Protéger les fichiers contenant des informations sensibles
Si vous choisissez d’utiliser un fichier de configuration ou un autre fichier externe pour stocker des informations sensibles, il est indispensable de protéger ce fichier avec des permissions strictes. Par exemple, vous pouvez utiliser la commande suivante pour restreindre l’accès :
Cela garantit que seul le propriétaire du fichier peut le lire ou le modifier.
Citer correctement les variables
Lorsque vous travaillez avec des scripts Bash, citer les variables correctement est une étape clé pour éviter les erreurs et les comportements imprévus. Si vous ne citez pas vos variables de manière adéquate, le shell peut mal interpréter les valeurs de ces variables, particulièrement lorsque celles-ci contiennent des espaces, des caractères spéciaux ou des chaînes vides.
Dans le contexte des scripts Bash, l’expression “citer les variables” fait référence à l’utilisation de guillemets autour des variables.
Dans un script shell, si une variable n’est pas entourée de guillemets, elle
est susceptible de subir des opérations involontaires de séparation de mots
(word-splitting) ou de globbing (expansion des caractères génériques comme
*
et ?
). Cela peut entraîner des erreurs ou des actions inattendues.
-
Séparation de mots (word-splitting) : Lorsque le shell rencontre une variable non citée, il la sépare en plusieurs mots si elle contient des espaces, ce qui peut provoquer des erreurs ou des résultats inattendus.
-
Globbing : Si une variable non citée contient des caractères spéciaux comme
*
ou?
, le shell peut les interpréter comme des caractères génériques, entraînant l’expansion de la variable pour correspondre à des fichiers ou répertoires du système de fichiers. Cela peut être dangereux si vous supprimez accidentellement des fichiers en utilisantrm *
, par exemple.
Exemple sans guillemets :
Le script va interpréter cette commande comme deux fichiers distincts : “mon” et “fichier”, et tentera de supprimer deux fichiers au lieu d’un seul. Cela pourrait causer des erreurs ou entraîner la suppression de fichiers non voulus.
Exemple avec guillemets :
En ajoutant des guillemets autour de la variable "$filename"
, vous vous
assurez que le nom de fichier complet, y compris les espaces, est interprété
comme un seul argument. Cela permet au script de fonctionner correctement, même
si des espaces ou d’autres caractères spéciaux sont présents dans les noms de
fichiers.
Gérer les erreurs efficacement
Un aspect souvent négligé dans les scripts Bash est la gestion des erreurs. La plupart du temps, lorsque nous écrivons un script, nous nous attendons à ce que tout se passe comme prévu. Cependant, il est indispensable de prendre en compte les situations où les choses pourraient mal tourner.
Pourquoi est-il important de gérer les erreurs ?
La gestion des erreurs permet d’éviter que le script ne continue d’exécuter des commandes dans des conditions imprévues. Par exemple, si une opération de suppression de fichier échoue, mais que le script continue de tourner sans se soucier de cette erreur, cela peut laisser des fichiers indésirables sur le système, voire conduire à des comportements encore plus graves dans des scénarios plus complexes.
Sans une bonne gestion des erreurs, il est difficile de savoir ce qui a échoué dans le script, et cela peut rendre le débogage extrêmement compliqué. Cela peut aussi entraîner des actions non désirées qui affectent la stabilité du système.
Ajouter une gestion d’erreurs basique
L’ajout d’une gestion d’erreurs dans un script Bash est assez simple et se
fait souvent en vérifiant le code de retour d’une commande, généralement
avec une commande conditionnelle comme if
ou &&
.
Exemple sans gestion d’erreurs :
Dans cet exemple, si la copie échoue pour une raison quelconque (par exemple, le fichier source n’existe pas), le script affichera toujours le message “Fichier copié avec succès.”, ce qui pourrait prêter à confusion.
Exemple avec gestion d’erreurs :
Ici, nous avons ajouté un bloc conditionnel pour vérifier si la commande
cp
a réussi. Si elle échoue, le script affiche un message d’erreur et quitte
avec un code d’erreur (généralement 1
pour indiquer une erreur générale).
Utilisation de trap
pour intercepter les erreurs
En plus des blocs conditionnels, Bash propose un mécanisme appelé trap
,
qui permet d’intercepter les signaux ou les erreurs dans un script. Cela permet
de nettoyer correctement les ressources (comme les fichiers temporaires) ou
d’afficher des messages utiles avant la fin du script, même en cas d’erreurs non
anticipées.
Exemple avec trap
:
Ici, nous utilisons trap
pour intercepter l’erreur et afficher un message
avant de quitter le script. Le mot-clé ERR
intercepte toutes les erreurs dans
le script, et la commande associée est exécutée automatiquement si une erreur
survient.
Utiliser set -euo pipefail
pour une gestion automatique des erreurs
Comme mentionné dans une section précédente, activer l’option set -euo pipefail
est une bonne pratique pour arrêter immédiatement l’exécution du
script dès qu’une erreur survient, éviter l’utilisation de variables non
définies et s’assurer que les erreurs dans les pipelines sont correctement
gérées. Cela simplifie la gestion des erreurs en automatisant l’arrêt du script
dès que quelque chose ne se passe pas comme prévu.
Exemple combiné :
Ce script est maintenant robuste et arrêtera son exécution dès qu’une erreur survient, tout en affichant un message d’erreur clair.
Importance des codes de retour
Chaque commande dans un script shell retourne un code de sortie. Un code
de sortie de 0
indique un succès, tandis qu’un code différent de 0
indique
un échec. Il est indispensable de prendre en compte ces codes de retour dans vos
scripts pour vous assurer que les commandes échouées sont gérées correctement.
Vous pouvez utiliser la commande $?
pour vérifier le code de retour de la
dernière commande exécutée. Si vous souhaitez capturer et gérer manuellement le
code de retour, vous pouvez le faire ainsi :
Protéger les fichiers temporaires
Les fichiers temporaires jouent souvent un rôle essentiel dans les scripts Bash. Ils permettent de stocker des données provisoires pendant l’exécution d’un script, mais s’ils ne sont pas correctement gérés, ils peuvent exposer votre système à des failles de sécurité. Une mauvaise gestion des fichiers temporaires peut être exploitée par des utilisateurs malveillants pour accéder à des données sensibles, ou pour écraser des fichiers critiques du système via une attaque par lien symbolique (symlink attack).
Pourquoi les fichiers temporaires sont une cible ?
Les fichiers temporaires sont généralement créés dans des répertoires
partagés comme /tmp
ou /var/tmp
, qui sont accessibles par tous les
utilisateurs du système. Si plusieurs utilisateurs peuvent accéder à ces
répertoires, il est possible pour un attaquant de créer ou modifier un fichier
temporaire avec le même nom que celui que votre script prévoit d’utiliser. En
l’absence de mécanismes de protection, cela peut conduire à :
- L’écrasement de fichiers : Si votre script crée un fichier temporaire sans vérifier s’il existe déjà, un attaquant peut créer un fichier à cet emplacement et forcer le script à écraser un fichier important du système.
- Les attaques par lien symbolique (symlink attack) : Un utilisateur malveillant peut créer un lien symbolique pointant vers un fichier sensible. Si le script accède à ce lien pensant qu’il s’agit d’un fichier temporaire, il pourrait lire ou écrire dans un fichier critique du système.
Comment sécuriser les fichiers temporaires ?
Pour éviter ces risques, voici quelques meilleures pratiques à suivre lors de la gestion des fichiers temporaires dans vos scripts Bash.
Utiliser mktemp
pour créer des fichiers et répertoires temporaires
L’une des méthodes les plus sûres pour créer des fichiers temporaires est
d’utiliser la commande mktemp
. Cette commande crée des fichiers ou des
répertoires temporaires avec des noms uniques, empêchant ainsi toute collision
avec des fichiers déjà existants.
Exemple :
Dans cet exemple, mktemp
garantit que le fichier temporaire créé est unique et
sécurisé, ce qui évite les collisions avec d’autres fichiers. Une fois le script
terminé, le fichier temporaire est supprimé avec rm -f
, ce qui libère de
l’espace et supprime les données sensibles.
Utiliser un répertoire temporaire privé avec mktemp -d
Si votre script nécessite un répertoire temporaire, vous pouvez utiliser
l’option -d
de mktemp
, qui crée un répertoire temporaire sécurisé. Cela est
particulièrement utile si votre script génère plusieurs fichiers temporaires.
Exemple :
Ici, le répertoire temporaire est sécurisé, et une fois que le script a terminé
son travail, il est supprimé avec la commande rm -rf
.
Vérifier les permissions des répertoires temporaires
Les répertoires /tmp
et /var/tmp
sont souvent partagés entre plusieurs
utilisateurs. Bien qu’ils soient configurés pour empêcher les utilisateurs
d’accéder aux fichiers des autres, il est recommandé de vérifier les
permissions des fichiers temporaires que vous créez.
Par exemple, vous pouvez restreindre les permissions pour qu’aucun autre utilisateur ne puisse accéder au fichier temporaire que vous créez :
Cela garantit que le fichier temporaire ne peut être lu ou modifié que par l’utilisateur qui l’a créé.
Supprimer les fichiers temporaires après utilisation
Il est essentiel de s’assurer que les fichiers temporaires sont supprimés après leur utilisation. Cela empêche tout utilisateur malveillant de retrouver des fichiers qui pourraient contenir des données sensibles.
Utilisez toujours rm -f
pour supprimer les fichiers temporaires à la fin de
votre script :
Cela garantit que même si le script échoue ou se termine prématurément, les fichiers temporaires seront nettoyés.
Ajouter des messages de log pour le débogage
L’ajout de messages de log dans vos scripts Bash est une pratique souvent sous-estimée, mais elle peut grandement faciliter le débogage et améliorer la transparence de l’exécution du script.
Pourquoi ajouter des messages de log ?
Sans messages de log, il est difficile de suivre l’exécution d’un script, surtout dans des environnements de production ou lors de l’automatisation de tâches critiques. Les logs permettent de :
- Diagnostiquer les erreurs : Vous pouvez savoir où et pourquoi une erreur est survenue, ce qui facilite le débogage.
- Suivre l’exécution : Les logs montrent quelle partie du script est en cours d’exécution et si tout se déroule comme prévu.
- Audit : En cas de problème de sécurité ou de dysfonctionnement, les logs peuvent fournir des informations précieuses sur ce qui s’est passé.
Comment ajouter des messages de log dans un script Shell ?
Il existe plusieurs façons de créer des messages de log dans un script Bash. Voici quelques pratiques essentielles :
Utilisation de la commande echo
pour des logs simples
L’utilisation la plus basique consiste à afficher des messages avec echo
.
C’est une manière simple d’afficher ce qui se passe dans le script au fur et à
mesure de son exécution.
Exemple :
Dans cet exemple, les messages affichés par echo
permettent de suivre
l’exécution du script et de voir si les différentes étapes sont réussies ou
échouent.
Rediriger les logs vers un fichier
Au lieu d’afficher les messages de log directement dans la console, vous pouvez rediriger les sorties vers un fichier de log pour les conserver et les analyser plus tard. Cela est particulièrement utile dans un environnement de production où vous voulez garder une trace des opérations effectuées.
Exemple avec redirection :
Dans cet exemple, toutes les sorties sont redirigées vers un fichier de log
situé dans /var/log/mon_script.log
. Cela permet de conserver une trace des
événements même après la fin du script.
Utilisation de logger
pour des journaux système
Pour une gestion encore plus robuste des logs, vous pouvez utiliser la commande
logger
, qui permet d’envoyer des messages au système de journalisation
(syslog) du système d’exploitation. Ces logs peuvent ensuite être consultés dans
des fichiers système tels que /var/log/syslog
ou /var/log/messages
, selon la
configuration de votre système.
Exemple avec logger
:
Avec logger
, les messages sont automatiquement envoyés au système de
journalisation, ce qui permet une gestion centralisée des logs, particulièrement
utile dans des environnements multi-utilisateurs ou des serveurs.
Ajouter des options de verbosité**
Pour rendre le script plus flexible, vous pouvez ajouter une option de
verbosité (mode verbose) qui permettra de contrôler si les messages de log
doivent être affichés ou non. Cela peut être fait en utilisant une variable
verbose
qui est activée ou désactivée via les arguments du script.
Exemple avec une option de verbosité :
Avec cette approche, l’utilisateur peut activer le mode verbose en exécutant le
script avec l’option -v
, ce qui affichera les messages de log. Sinon, le
script fonctionne de manière silencieuse sans afficher les logs.
Utilisation de exit
Dans le cadre de la sécurisation des scripts Bash, l’utilisation correcte de
la commande exit
peut être utile pour contrôler la façon dont un script se
termine. En définissant un code de sortie explicite, vous garantissez que les
autres processus ou scripts qui appellent votre script sont correctement
informés de son succès ou de son échec, ce qui permet de prévenir des
comportements imprévus ou dangereux.
Exemple :
Dans ce script :
exit 0
signale que la suppression s’est bien déroulée.exit 1
signale un échec en raison de l’absence du fichier.
Le code complet sécurisé
Utilisation de ShellCheck pour analyser et améliorer vos scripts
ShellCheck est un outil d’analyse statique conçu pour examiner les scripts shell, comme ceux écrits en Bash, et détecter les erreurs, les mauvaises pratiques, ainsi que des vulnérabilités potentielles. C’est un outil précieux pour les administrateurs systèmes et les développeurs qui veulent s’assurer que leurs scripts sont corrects, sécurisés et faciles à maintenir.
ShellCheck peut être utilisé en ligne, installé localement sur votre machine, ou intégré dans des éditeurs de texte comme VS Code. Voici quelques façons de l’utiliser :
Si vous ne souhaitez pas installer l’outil, vous pouvez simplement copier et coller votre script sur le site web de ShellCheck (ShellCheck Online ↗) pour obtenir un rapport d’analyse.
Vous pouvez installer ShellCheck sur votre machine via un gestionnaire de paquets. Voici un exemple d’installation sur Ubuntu :
Une fois installé, vous pouvez exécuter l’outil en ligne de commande sur vos scripts :
Conclusion
Les scripts Bash, même simples, peuvent devenir des cibles d’attaques si on ne respecte pas certaines règles de base. Mais en adoptant progressivement ces bonnes pratiques, et avec l’aide d’outils comme ShellCheck, vous développez des réflexes de sécurité et d’optimisation qui garantiront la stabilité et la fiabilité de vos scripts.
Cela peut sembler fastidieux au début. Entre l’ajout de validations d’entrées, la gestion des permissions, l’utilisation de commandes sécurisées et la protection contre les erreurs, la liste des pratiques à suivre peut paraître longue et complexe. Cependant, plus vous pratiquez, plus ces techniques deviennent automatiques et naturelles.
Ainsi, prenez le temps de mettre en pratique ces recommandations et vous verrez que l’effort initial sera largement récompensé par la tranquillité d’esprit et la qualité de vos scripts Bash.