Wie kann ich temporäre Dateien aus Shell-Skripten sicher erstellen und darauf zugreifen?

14

Ich habe gelesen, dass das Umleiten der Ausgabe in eine Datei mit festem Namen /tmpein Sicherheitsrisiko darstellen kann, da ein Angreifer (oder ein Angreifer mit falschem Inhalt) bemerkt, dass eine Datei /tmp/tmpfileformyscript.tmperstellt wird, wenn ich mein Skript ausführe (auch wenn er keinen Lesezugriff auf meine Datei hat) Skript) kann er zum Beispiel einen Symlink erstellen, der ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmpmich veranlasst, meine .bashrcDatei zu zerstören , wenn ich mein Skript ausführe.

Also kann ich stattdessen sowas benutzen filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename".

Ich möchte jedoch manchmal eine tmp-Datei zum Zwischenspeichern verwenden. In diesem Fall möchte ich wissen, ob "tmpfile.tmp. *" Mit etwas übereinstimmt, /tmpund in diesem Fall diese Datei verwenden, anstatt eine neue zu erstellen. Leider testund das Äquivalent [ -f filename ]unterstützt keine Datei-Globbing, soweit ich das beurteilen kann.

Daher habe ich zwei Fragen:

  1. Wie kann ich sicher ein tempfile erstellen? Gibt es "predictablename.$RANDOM"eine akzeptable Praxis oder einen besseren (sichereren, einfacheren) Weg?
  2. Wie kann ich einfach auf die Datei zugreifen und / oder ihre Existenz später durch Prüfen auf feststellen predictablename?
Platzhalter
quelle

Antworten:

13

Verwenden Sie das mktempDienstprogramm, um eine temporäre Datei mit einem unvorhersehbaren Namen zu erstellen. Es ist nicht von POSIX standardisiert, aber sowohl auf * BSD als auch auf Linux verfügbar.

> /tmp/predictable.$RANDOMDies ist keine gute Wahl, da es meistens vorhersehbar ist¹, wodurch Ihr Skript für einen Angriff geöffnet wird, bei dem der Angreifer Ihr Skript dazu verleiten kann, eine Datei zu überschreiben, auf die Sie Schreibzugriff haben, oder ihnen Zugriff auf die temporäre Datei zu gewähren. Dies ist eine unsichere Sicherheitsanfälligkeit für temporäre Dateien . mktemphat diese Sicherheitsanfälligkeit nicht, da die Datei sicher erstellt wird (es wird keine vorhandene Datei überschrieben, auch wenn symbolische Links vorhanden sind) und ein ausreichend unvorhersehbarer Name verwendet wird, um einen Denial-of-Service zu vermeiden.

Wenn es nicht gut genug ist, eine temporäre Datei zu erstellen und damit zu arbeiten, erstellen Sie ein temporäres Verzeichnis mit mktemp -dund arbeiten Sie dort.

mktempEs wird auch darauf geachtet, $TMPDIRwenn die Variable gesetzt ist, und auf zurückzugreifen, /tmpwenn sie nicht gesetzt ist.

Immer mehr Distributionen TMPDIRwerden als privates Verzeichnis eingerichtet, z. B. /run/1234/tmpwo 1234ist Ihre UID. Hierdurch wird das Risiko von Sicherheitslücken in Bezug auf temporäre Dateien beseitigt, da temporäre Dateien nicht mehr zwischen Benutzern ausgetauscht werden können (was gelegentlich nützlich ist, aber nicht sehr häufig; /tmpist immer noch verfügbar, nur nicht TMPDIR).

Wenn Sie einen reproduzierbaren Dateinamen benötigen, erstellen Sie eine Datei mit einem genau definierten Namen (ohne zufällige Komponente) im Basisverzeichnis des Benutzers. Die moderne Konvention ist die XDG-Benutzerverzeichnisspezifikation . Wenn die Datei ohne Datenverlust entfernt werden konnte, verwenden Sie die XDG_CACHE_HOMEUmgebungsvariable mit dem Standardwert "" ~/.cache. Sie sollten wahrscheinlich ein nach Ihrer Anwendung benanntes Unterverzeichnis erstellen und dort arbeiten.

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

¹ Nimmt nicht $RANDOMnur 32767 mögliche Werte an, sondern ist auch leicht vorherzusagen, ohne viele Werte auszuprobieren. Der Zufallszahlengenerator von Bash ist eine LCG , die nach PID und Zeitpunkt der ersten Verwendung geimpft wird. Zsh ist der Startzeitpunkt der Plattform rand. ATT Ksh's ist die Plattform, die randvon PID geimpft wird. Mkshs ist eine LCG mit einem komplexeren, aber immer noch nicht sicherheitsrelevanten Saatgut. Alle von ihnen können durch einen anderen Prozess mit einer ziemlich großen Erfolgschance vorhergesagt werden.

Gilles 'SO - hör auf böse zu sein'
quelle
Eigentlich ist deine Diskussion von $TMPDIRund ~/.cachegenau das, was ich brauchte. Nach einigen weiteren Überlegungen wurde mir klar, dass der einzige Grund, warum ich es wollte, /tmpdie Partitionierung war - also konnte der Cache die /homePartition nicht füllen . Aber für diesen Anwendungsfall ist das wirklich kein Problem, sodass ein Unterverzeichnis ~/.cachemeiner Anforderungen perfekt entspricht und die Sicherheitslücke schließt.
Wildcard
mktempist unter AIX oder der Git-Shell unter Windows nicht verfügbar. Es sieht aus wie file.$RANDOM$RANDOMist die portable Lösung. Der $RANDOM$RANDOMSpeicherplatz sollte auf 2 ^ 32 erhöht werden, vorausgesetzt, die zufälligen Bash-Ergebnisse sind unabhängig und nicht schwach.
Die zufälligen Ergebnisse von @jww Bash sind schwach: Es handelt sich um eine LCG, die für viele Anwendungen, die keine Unvorhersehbarkeit erfordern, so gut wie vorhersehbar ist.
Gilles 'SO - hör auf böse zu sein'
9

Dafür wurde mktemp entwickelt. Von der Manpage:

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

mktemp erstellt die Datei oder beendet sie mit einem Exit-Status ungleich Null. Das logische oder (||) stellt sicher, dass das Skript beendet wird, wenn mktemp die Datei nicht erstellen kann. Nach diesem Befehl können Sie sicher sein, dass die Datei verfügbar ist. Es besteht keine Notwendigkeit, es erneut zu überprüfen. Das einzige, was Sie möglicherweise hinzufügen müssen, ist die Bereinigung der Datei am Ende Ihres Skripts.

Und möglicherweise auch, wenn das Skript durch ein Signal beendet wird. Ob das notwendig ist oder nicht, müssen Sie entscheiden.

Beides kann mit dem trapBefehl erfolgen.

Bram
quelle
Ah! Das ist sehr nützlich; dann muss ich nicht anrufen $RANDOM. Aber dann Teil 2 meiner Frage: Wie kann ich später auf diese Datei zugreifen oder prüfen, ob sie bei einer nachfolgenden Ausführung des Skripts bereits vorhanden ist? (Um einen sehr einfachen Cache zu implementieren.)
Wildcard