FlawOpen

flawopen.com/Command Injection/exec() vs. execFile()

exec() vs. execFile() in Node.js: Wo liegt der Unterschied?

Referenzleitfaden
Kurzantwort

exec() erhält einen String und führt ihn in einer Shell aus: Pipes und Platzhalter funktionieren, aber Metazeichen in nicht vertrauenswürdigen Eingaben können auch den Befehl verändern. execFile() startet das angegebene Programm direkt mit einem Argumentarray und standardmäßig ohne Shell. Das verhindert Shell-Parsing, aber nicht jedes Risiko: Das Zielprogramm kann ein Argument weiterhin als Option interpretieren oder auf einen unerwarteten Wert reagieren.

Vergleich

exec() — verwendet eine Shell
exec(`ls ${dir} | grep .txt`,
  (err, out) => {...})
// die Pipe funktioniert, aber auch Shell-Metazeichen.
execFile() — standardmäßig ohne Shell
execFile('ls', [dir],
  (err, out) => {...})
// ohne Shell; prüfen Sie, wie ls das Argument dir interpretiert.
// break out of its own argument

Wann Sie Shell-Funktionen tatsächlich benötigen

Wenn ein Befehl Pipes, Platzhaltererweiterung oder Umleitungen benötigt, kann execFile() diese Funktionen nicht direkt abbilden. Bauen Sie die Pipeline vorzugsweise in Node.js auf, indem Sie jede Stufe separat starten und die Streams verbinden. Wenn exec() unvermeidbar ist, dürfen nicht vertrauenswürdige Eingaben nicht in den Befehlsstring gelangen. Shell-freie Argumentarrays verhindern außerdem keine Argument-Injection: Validieren Sie jeden Wert passend zum Zielprogramm, verwenden Sie --, wenn das Programm es unterstützt, und erlauben Sie nur vorgesehene Befehle und Optionen. Die Option shell: true aktiviert eine Shell bei APIs, die standardmäßig keine starten; übergeben Sie dabei niemals ungeprüfte Eingaben.

Häufige Fragen

Windows-Batchdateien verändern die Sicherheitsgrenze

Unter Windows lassen sich .bat- und .cmd-Dateien nicht direkt mit execFile() starten. Node dokumentiert den Aufruf über exec(), cmd.exe oder spawn() mit aktiviertem Shell-Modus; dabei wird die Interpretation durch einen Kommandointerpreter wieder eingeführt. Bevorzugen Sie ein natives ausführbares Programm oder eine direkte API. Wenn ein Batch-Aufruf unvermeidbar ist, halten Sie Skriptpfad und Argumente fest oder validieren Sie sie anhand des genauen Skriptvertrags. Node stuft außerdem ein Argumentarray mit shell: true als veraltet ein (seit v22.15.0 und v23.11.0).

Ist spawn() dasselbe wie execFile()?

spawn() arbeitet standardmäßig ebenfalls ohne Shell und akzeptiert ein Argumentarray. Der wichtigste praktische Unterschied ist die Ausgabe: spawn() liefert Streams, während execFile() die Ausgabe puffert. Keine der beiden Funktionen verhindert, dass das Programm ein Argument als Option interpretiert; validieren Sie es für das jeweilige Programm. shell: true aktiviert wieder das Shell-Parsing.

Quellen

Siehe auch Befehlsinjektion ins Betriebssystem (CWE-78): Funktionsweise und Schutz in jeder Sprache — flawopen.com Java Runtime.exec() und Command Injection: Was ändert sich? Command-Injection-Risiko bei Node.js exec()