Acceptation sécurisée des entrées utilisateur : Techniques essentielles pour la commande read de Bash
Lors de la création de scripts Bash interactifs, demander des entrées à l'utilisateur est une exigence courante. La commande intégrée read est l'outil standard pour cette tâche. Cependant, accepter simplement une entrée sans tenir compte de la sécurité et de la robustesse peut entraîner des vulnérabilités et des échecs de script. Cet article explore les techniques essentielles pour demander et lire de manière sécurisée et efficace les entrées utilisateur dans vos scripts Bash, couvrant des aspects tels que la gestion des mots de passe, les délais d'attente et l'assainissement basique des variables.
Comprendre comment utiliser correctement read est crucial pour créer des scripts shell fiables et sécurisés. Que vous automatisiez des tâches d'administration système, créiez des outils interactifs ou recueilliez des détails de configuration, un mécanisme d'entrée bien conçu garantit que votre script se comporte comme prévu et n'expose pas d'informations sensibles ni ne succombe à des données malformées.
Les bases de la commande read
Par défaut, la commande read lit une ligne depuis l'entrée standard et l'affecte à une ou plusieurs variables. L'utilisation la plus courante consiste à lire une seule ligne dans une seule variable.
echo "Veuillez entrer votre nom :"
read nom_utilisateur
echo "Bonjour, $nom_utilisateur !"
Dans cet exemple simple, le script demande à l'utilisateur et stocke son entrée dans la variable nom_utilisateur. L'option -p est un moyen plus concis d'afficher une invite sans avoir besoin d'une commande echo séparée :
read -p "Veuillez entrer votre âge : " age_utilisateur
echo "Vous avez entré $age_utilisateur ans."
Gestion des entrées sensibles : Mots de passe
Lorsque vous traitez des informations sensibles comme des mots de passe, vous devez empêcher leur affichage sur le terminal. La commande read fournit l'option -s (silencieux) à cette fin.
read -s -p "Entrez votre mot de passe : " mot_de_passe
echo
# Il est généralement déconseillé de réafficher le mot de passe, même masqué
# echo "Mot de passe entré (masqué)."
# Vous pourriez vouloir confirmer le mot de passe
read -s -p "Confirmez votre mot de passe : " confirmation_mot_de_passe
echo
if [ "$mot_de_passe" == "$confirmation_mot_de_passe" ]; then
echo "Les mots de passe correspondent. Continuation..."
else
echo "Les mots de passe ne correspondent pas. Sortie."
exit 1
fi
Note de sécurité importante : Même avec -s, le mot de passe est stocké dans la variable $mot_de_passe en texte clair en mémoire. Évitez de l'imprimer, de le stocker dans des journaux ou de l'utiliser de manière non sécurisée plus tard dans votre script. Pour une gestion des mots de passe plus robuste, envisagez des outils ou des bibliothèques externes si votre application l'exige.
Définir des limites de temps pour les entrées
Parfois, vous voudrez peut-être limiter le temps dont dispose un utilisateur pour répondre. L'option -t vous permet de spécifier un délai d'attente en secondes. Si le délai d'attente est atteint avant que l'utilisateur n'ait fourni d'entrée, read renverra un statut de sortie non nul.
read -p "Vous avez 5 secondes pour entrer votre couleur préférée : " -t 5 couleur_preferee
if [ $? -eq 0 ]; then
echo "Votre couleur préférée est $couleur_preferee."
else
echo "Délai d'attente dépassé ! Aucune entrée reçue."
fi
Ceci est utile pour les scripts qui doivent continuer même si l'utilisateur ne répond pas, empêchant ainsi le script de rester bloqué indéfiniment.
Lecture de plusieurs valeurs
La commande read peut également être utilisée pour lire plusieurs mots à partir d'une ligne, en les affectant à des variables successives. Le délimiteur utilisé est le séparateur de champs interne (IFS), qui est par défaut l'espace, la tabulation et le saut de ligne.
read -p "Entrez votre prénom et votre nom : " prenom nom
echo "Prénom : $prenom"
echo "Nom : $nom"
Si l'utilisateur saisit plus de mots qu'il n'y a de variables, la dernière variable contiendra le reste de la ligne.
Pour lire une ligne entière dans une seule variable, même si elle contient des espaces, vous pouvez utiliser read nom_variable sans aucune autre option (comme montré dans les exemples de base) ou utiliser explicitement un tableau si vous souhaitez conserver les espaces dans les mots mais les diviser par des espaces blancs :
read -p "Entrez votre adresse complète : " -a parties_adresse
# 'parties_adresse' sera un tableau. Le premier élément est le premier mot, le deuxième est le deuxième, etc.
# Si l'entrée est "123 Rue Principale", parties_adresse[0]=123, parties_adresse[1]=Rue, parties_adresse[2]=Principale
# Pour les joindre à nouveau ou traiter les parties individuelles :
adresse_complete="${parties_adresse[*]}"
echo "Adresse complète : $adresse_complete"
Validation et assainissement des entrées
Bien que read lui-même n'effectue pas de validation sophistiquée, il est crucial de valider et d'assainir les entrées que vous recevez avant de les utiliser, surtout si elles sont utilisées dans des commandes, des chemins de fichiers ou d'autres opérations sensibles.
Exemples de validation basiques :
-
Vérification d'une entrée vide :
bash read -p "Entrez une valeur requise : " valeur_requise if [ -z "$valeur_requise" ]; then echo "Erreur : L'entrée ne peut pas être vide." exit 1 fi -
Vérification si l'entrée est numérique :
bash read -p "Entrez un nombre : " nombre if ! [[ "$nombre" =~ ^[0-9]+$ ]]; then echo "Erreur : Veuillez entrer un entier positif valide." exit 1 fi
Ceci utilise une expression régulière pour s'assurer que l'entrée ne contient que des chiffres. -
Assainissement pour l'exécution de commandes : Si l'entrée utilisateur doit être utilisée dans le cadre d'une commande, soyez extrêmement prudent. Une entrée malveillante pourrait entraîner une injection de commande. L'approche la plus sûre est souvent d'éviter d'intégrer directement l'entrée utilisateur dans les commandes. Si vous devez le faire, envisagez d'échapper les caractères spéciaux, mais c'est complexe et sujet aux erreurs. L'utilisation de
printf %qpeut aider à citer les arguments en toute sécurité pour l'exécution du shell :
bash read -p "Entrez un nom de fichier (sans espaces ni caractères spéciaux) : " nom_fichier # Vérification basique pour les noms de fichiers simples, évitant le parcours de répertoire if [[ "$nom_fichier" =~ ^[a-zA-Z0-9_.-]+$ ]]; then nom_fichier_securise=$(printf %q "$nom_fichier") # Citer en toute sécurité le nom de fichier echo "Traitement du fichier : $nom_fichier_securise" # Commande exemple - attention ! # cat $nom_fichier_securise # Cela pourrait toujours être risqué si le nom de fichier est élaboré else echo "Erreur : Caractères invalides dans le nom de fichier." exit 1 fi
Contrôle du délimiteur
Par défaut, read divise l'entrée en fonction de IFS. Vous pouvez le modifier en utilisant l'option -d pour spécifier un délimiteur. Ceci est moins courant pour les entrées interactives mais utile lors de la lecture de fichiers ou de flux de données spécifiques.
Pour les invites interactives, vous voulez généralement lire jusqu'à un saut de ligne, ce qui est le comportement par défaut.
Bonnes pratiques pour les entrées utilisateur
- Soyez clair avec les invites : Indiquez à l'utilisateur exactement ce que vous attendez (par exemple, "Entrez la date au format AAAA-MM-JJ :").
- Fournissez un retour : Confirmez ce que l'utilisateur a entré, surtout pour les données critiques.
- Validez les entrées : Vérifiez toujours si l'entrée répond aux exigences de votre script (par exemple, est-elle vide, est-ce un nombre, correspond-elle à un modèle).
- Assainissez les entrées sensibles : N'affichez jamais les mots de passe. Gérez-les avec soin.
- Gérez les erreurs avec grâce : Informez l'utilisateur lorsque l'entrée est invalide ou qu'un délai d'attente est dépassé et fournissez un chemin de sortie clair.
- Considérez les cas limites : Que se passe-t-il si l'utilisateur appuie immédiatement sur Entrée ? Que se passe-t-il s'il colle une grande quantité de texte ?
Conclusion
La commande read est un outil puissant pour créer des scripts Bash interactifs. En comprenant ses options comme -p pour les invites, -s pour les entrées silencieuses et -t pour les délais d'attente, vous pouvez créer des scripts plus robustes et conviviaux. Plus important encore, en mettant en œuvre une validation et un assainissement de base, vous pouvez améliorer considérablement la sécurité et la fiabilité de vos scripts shell, en évitant les pièges courants et les vulnérabilités potentielles.