Retour au cours

securite

Objectifs

  • Comprendre les risques de sécurité les plus courants en scripting Bash (injections, word splitting).
  • Appliquer un “quoting” (usage des guillemets) strict pour prévenir ces failles.
  • Valider les entrées externes pour éviter l’exécution de code arbitraire.
  • Se méfier des commandes et variables dangereuses comme eval et IFS.

Explications détaillées

Notions clés

Écrire des scripts Bash sûrs repose sur quelques principes fondamentaux, souvent négligés. Une simple erreur de guillemets peut transformer un script anodin en une faille de sécurité béante.

Le Quoting est la Sécurité Numéro 1

La grande majorité des vulnérabilités en shell viennent de variables non citées. Lorsque le shell rencontre une variable non entourée de guillemets doubles, il effectue deux opérations dangereuses :

  1. Word Splitting : Il découpe la valeur de la variable en plusieurs “mots” en se basant sur les espaces, tabulations et sauts de ligne.
  2. Glob Expansion : Il interprète les caractères jokers comme *, ?, [].

Exemple de catastrophe :

NOM_FICHIER="Mon rapport important.txt"
# Sans guillemets, la commande devient : rm Mon rapport important.txt
# rm essaiera de supprimer 3 choses : "Mon", "rapport", et "important.txt"
rm $NOM_FICHIER # DANGEREUX

# La bonne façon :
rm "$NOM_FICHIER" # Sûr, la commande voit un seul argument

Règle d’or : TOUJOURS citer les expansions de variables : "$VAR", "$@", "$(commande)".

Injection de Commandes

Si votre script utilise une entrée externe (argument, saisie utilisateur) pour construire une commande, un attaquant peut y injecter ses propres commandes.

# Script vulnérable
read -p "Entrez un nom de domaine à pinger : " HOST
ping -c 1 $HOST # DANGEREUX

Si l’utilisateur tape google.com; rm -rf ~, la commande deviendra ping -c 1 google.com; rm -rf ~, et le script effacera son dossier personnel.

Solution : Valider et nettoyer les entrées. Ne jamais faire confiance.

Chemins et la variable PATH

Si votre script appelle une commande simple comme ls, il utilise la variable PATH pour la trouver. Si un attaquant peut modifier le PATH pour y insérer un dossier contenant une version malveillante de ls, il peut exécuter du code arbitraire.

Solution : Dans les scripts très sensibles (exécutés en tant que root), utilisez des chemins absolus pour les commandes critiques : /bin/ls, /usr/bin/grep.

eval est le mal (eval is evil)

La commande eval prend une chaîne de caractères et l’exécute comme si elle avait été tapée dans le shell. C’est l’équivalent de donner les clés de votre système à une chaîne de caractères. Ne l’utilisez jamais avec des données dont vous ne contrôlez pas à 100% l’origine et le contenu.

Syntaxe / Usages

# Mauvais : vulnérable au word splitting et globbing
touch $FILENAME

# Bon : sûr
touch "$FILENAME"

# Mauvais : vulnérable à l'injection
read HOST
ssh root@$HOST

# Bon : validation (très basique)
read HOST
# Valide que HOST ne contient que des caractères "sûrs"
if [[ "$HOST" =~ ^[a-zA-Z0-9.-]+$ ]]; then
  ssh "root@$HOST"
else
  echo "Nom d'hôte invalide" >&2
  exit 1
fi

Exemples

# Créez des fichiers pour voir le problème
touch "un fichier.txt" "deux.txt"

# Sans guillemets
FICHIERS=$(ls)
for f in $FICHIERS; do
  echo "-> $f"
done
# Affiche "un", "fichier.txt", "deux.txt" sur des lignes séparées. Incorrect.

# Avec un tableau et des guillemets
FICHIERS_ARRAY=(*)
for f in "${FICHIERS_ARRAY[@]}"; do
  echo "-> '$f'"
done
# Affiche "-> 'un fichier.txt'", "-> 'deux.txt'". Correct.

Bonnes pratiques de sécurité

  • set -euo pipefail : Commencez toujours vos scripts avec cette ligne.
  • Citez TOUT : "$VAR", "$@", "$(cmd)".
  • Validez les entrées : Ne faites jamais confiance aux données venant de l’extérieur. Vérifiez les formats, les caractères autorisés.
  • Utilisez des chemins absolus pour les commandes dans les scripts sensibles.
  • N’utilisez pas eval. Il y a presque toujours une meilleure solution (tableaux, fonctions).

Pièges courants

  • Penser que le quoting est optionnel : C’est la porte d’entrée de la plupart des failles.
  • Construire des commandes en concaténant des chaînes : C’est une invitation aux injections. Préférez passer les variables comme des arguments distincts à vos commandes.
  • Parser la sortie de ls : Ne le faites jamais. ls est un outil d’affichage pour les humains, pas pour les scripts.

Exercices

  1. Le fichier nommé * :

    • Dans un dossier vide, créez un fichier nommé *.
    • Créez aussi deux autres fichiers, a.txt et b.txt.
    • Exécutez VAR="*"; echo $VAR. Que se passe-t-il ?
    • Maintenant, exécutez VAR="*"; echo "$VAR". Quelle est la différence ?
  2. Script de recherche “sûr” :

    • Écrivez un script search.sh qui prend un motif de recherche en premier argument et un nom de fichier en deuxième.
    • Le script doit exécuter grep "$MOTIF" "$FICHIER".
    • Assurez-vous que le script fonctionne correctement même si le motif ou le nom de fichier contiennent des espaces ou des caractères spéciaux.
  3. Prévention d’injection :

    • Créez un script qui prend un nom d’utilisateur en argument et affiche le contenu de son dossier personnel avec ls.
    • Montrez comment un utilisateur malveillant pourrait passer un argument comme toto; ls /root pour essayer de lister un autre dossier.
    • Corrigez le script en validant que l’argument ne contient que des caractères alphanumériques.