Comment puis-je créer et accéder en toute sécurité aux fichiers temporaires à partir de scripts shell?

14

J'ai lu que la redirection de la sortie vers un fichier de nom fixe dans /tmppeut être un risque pour la sécurité, car si un attaquant (ou un mécontent) remarque qu'un fichier /tmp/tmpfileformyscript.tmpest créé lorsque j'exécute mon script (même s'il n'a pas accès en lecture à mon script), il peut par exemple créer un lien symbolique ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmpqui me fera détruire mon .bashrcfichier lors de l'exécution de mon script.

Donc, à la place, je peux utiliser quelque chose comme filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename".

Cependant, j'aimerais parfois utiliser un fichier tmp pour la mise en cache, auquel cas je voudrais savoir si "tmpfile.tmp. *" Correspond à quoi que ce soit /tmpet si c'est le cas, utilisez ce fichier plutôt que d'en créer un nouveau. Malheureusement testet l'équivalent [ -f filename ]ne prend pas en charge la globalisation des fichiers pour autant que je sache.

Ma question est donc double:

  1. Comment puis-je créer un fichier temporaire en toute sécurité? Est-ce "predictablename.$RANDOM"une pratique acceptable ou existe-t-il un meilleur moyen (plus sûr, plus facile)?
  2. Comment puis-je accéder facilement au fichier et / ou établir son existence ultérieurement en vérifiant predictablename?
Caractère générique
la source

Réponses:

13

Utilisez l' mktemputilitaire pour créer un fichier temporaire avec un nom imprévisible. Il n'est pas standardisé par POSIX, mais il est disponible sur * BSD ainsi que Linux.

> /tmp/predictable.$RANDOMn'est pas un bon choix car il est principalement prévisible¹, ce qui ouvre votre script à une attaque où l'attaquant peut tromper votre script en écrasant un fichier auquel vous avez accès en écriture ou en lui donnant accès au fichier temporaire. Il s'agit d'une vulnérabilité de fichier temporaire non sécurisée . mktempn'a pas cette vulnérabilité car crée le fichier en toute sécurité (il n'écrasera pas un fichier existant, même si des liens symboliques sont impliqués) et utilise un nom suffisamment imprévisible pour éviter un déni de service.

Si la création d'un fichier temporaire et son utilisation ne sont pas suffisantes, créez un répertoire temporaire avec mktemp -det travaillez dedans.

mktempprend également soin d'utiliser $TMPDIRsi la variable est définie, en retombant /tmpsi elle n'est pas définie.

De plus en plus de distributions configurées TMPDIRpour être un répertoire privé, par exemple/run/1234/tmp où se 1234trouve votre UID. Cela élimine le risque de vulnérabilités de fichiers temporaires, au prix de ne plus pouvoir partager de fichiers temporaires entre utilisateurs (ce qui est parfois utile, mais pas très fréquent; /tmpest toujours disponible, mais pas TMPDIR).

Si vous avez besoin d'un nom de fichier reproductible, créez un fichier avec un nom bien défini (sans composant aléatoire) sous le répertoire personnel de l'utilisateur. La convention moderne est la spécification du répertoire utilisateur XDG . Si le fichier peut être supprimé sans provoquer de perte de données, utilisez la XDG_CACHE_HOMEvariable d'environnement, par défaut~/.cache . Vous devriez probablement créer un sous-répertoire nommé d'après votre application et y travailler.

CACHE_DIR="${XDG_CACHE_HOME:-"$HOME/.cache"}"/Wildcard-scripts
[ -d "$CACHE_DIR" ] || mkdir -p -- "$CACHE_DIR"
CACHE_FILE="$CACHE_DIR/tmpfileformyscript"

¹ Non seulement ne $RANDOMprend que 32 767 valeurs possibles, mais il est facile de prédire sans même essayer de nombreuses valeurs. Le générateur de nombres aléatoires de Bash est un LCG ensemencé par le PID et l'heure de la première utilisation. Zsh est la plate-forme randsemée par le temps de démarrage. ATT Ksh's est la plateforme randlancée par PID. Mksh's est un LCG avec une graine plus complexe, mais toujours pas de qualité sécuritaire. Tous peuvent être prédits par un autre processus avec une assez grande chance de succès.

Gilles 'SO- arrête d'être méchant'
la source
En fait, votre discussion $TMPDIRet ~/.cachec'est exactement ce dont j'avais besoin. Après mûre réflexion, je me suis rendu compte que la seule raison pour laquelle je le souhaitais /tmpétait le partitionnement — donc le cache ne pouvait pas remplir la /homepartition. Mais pour ce cas d'utilisation qui est vraiment un non-problème complet, un sous-répertoire de ~/.cachecorrespond parfaitement à mes besoins et évite le problème de sécurité.
Wildcard
mktempn'est pas disponible sous AIX ou le shell Git sous Windows. Il semble que ce file.$RANDOM$RANDOMsoit la solution portable. Le $RANDOM$RANDOMdevrait augmenter l'espace à 2 ^ 32, en supposant que les résultats aléatoires de Bash sont indépendants et non faibles.
Les résultats aléatoires de @jww Bash sont faibles: c'est un LCG, qui est à peu près aussi prévisible que possible tout en étant assez bon pour de nombreuses applications qui ne nécessitent pas d'imprévisibilité.
Gilles 'SO- arrête d'être méchant'
9

mktemp a été conçu pour cela. Depuis la page de manuel:

TMPFILE=`mktemp /tmp/example.XXXXXXXXXX` || exit 1
echo "program output" >> $TMPFILE

mktemp créera le fichier ou quittera avec un état de sortie différent de zéro. La logique ou (||) garantit que le script se fermera si mktemp n'est pas en mesure de créer le fichier. Après cette commande, vous pouvez être sûr que le fichier est disponible. Il n'est pas nécessaire de le vérifier à nouveau. La seule chose que vous devrez peut-être ajouter est le nettoyage du fichier à la fin de votre script.

Et peut-être aussi lorsque le script se termine par un signal. Que ce soit nécessaire ou non est quelque chose que vous devez décider.

Les deux peuvent être effectués à l'aide de la trapcommande.

Bram
la source
Ah! C'est très utile; alors je n'ai pas besoin d'appeler $RANDOM. Mais alors la partie 2 de ma question - comment puis-je accéder à ce fichier plus tard ou vérifier s'il existe déjà lors d'une exécution ultérieure du script? (Pour implémenter un cache très simple.)
Wildcard