flawopen.com/Command Injection/Node child_process.exec
Command-Injection-Risiko bei Node.js child_process.exec()
Eine Befehlszeichenfolge an exec() zu übergeben ist, als gäbe man einem Setzer einen Satz und ließe ihn anhand der Satzzeichen entscheiden, wo Anweisungen enden. Enthält nicht vertrauenswürdiger Text Shell-Syntax, kann die Shell sie als Steueranweisung lesen. execFile() übergibt ein festes Programm und getrennte Argumente; standardmäßig wird keine Shell geparst.
const { exec } = require('node:child_process');
function inspectFile(filename) {
return exec(`file ${filename}`);
}
const { execFile } = require('node:child_process');
const allowed = new Map([
['report-1', '/srv/reports/1.pdf'],
['report-2', '/srv/reports/2.pdf']
]);
function inspectReport(reportId) {
const path = allowed.get(reportId);
if (!path) throw new Error('Unknown report');
return execFile('/usr/bin/file', ['--', path], {
shell: false,
timeout: 3000,
maxBuffer: 64 * 1024
});
}
Warum execFile() das Command-Injection-Risiko senkt
exec() startet eine Shell und übergibt ihr eine Befehlszeichenfolge. Interpoliert der Code darin angreiferkontrollierten Text, interpretiert die Shell Metazeichen als Syntax: Das ist der in CWE-78 beschriebene Command-Injection-Pfad. execFile() startet eine bestimmte ausführbare Datei mit einem Argumentarray und erzeugt standardmäßig keine Shell; Shell-Trennzeichen werden daher nicht erneut von einer Shell ausgewertet. Das Beispiel ordnet außerdem eine übergebene ID einem festen Pfad zu. Dadurch ist nicht jedes Zielprogramm sicher: Validiere dessen Argumente, verwende einen Optionsterminator wie --, sofern unterstützt, und aktiviere für nicht vertrauenswürdige Werte niemals shell: true.
Unsichere exec()-Aufrufe finden
Suche nach exec() und execSync() und verfolge jede Befehlszeichenfolge bis zu Request-Parametern, Datenbankfeldern, Dateinamen und Umgebungsvariablen. Halte die ausführbare Datei und die Argumentgrenzen fest. Bevorzuge eine direkte API; andernfalls nutze execFile() mit fester ausführbarer Datei, validierten Argumenten, Zeitlimit und begrenzter Ausgabe.
grep -RInE 'exec(Sync)?[[:space:]]*\(' --include='*.js' --include='*.cjs' --include='*.mjs' --include='*.ts' .Synchrone Varianten
execSync() nutzt dieselbe shellbasierte Befehlszeichenfolge und hat dasselbe Injektionsrisiko; zusätzlich blockiert es die Event Loop. execFileSync() vermeidet standardmäßig die Shell-Auswertung, aber ausführbare Datei und Argumente müssen weiterhin validiert werden.