FlawOpen

flawopen.com/Command Injection/Java Runtime.exec()

Schützt Java Runtime.exec() vor Command Injection?

CWE-78: OS Command InjectionReferenzseite
Kurzantwort

Runtime.exec(String) startet nicht implizit eine Shell; Shell-Operatoren werden daher nicht automatisch interpretiert. Der String wird dennoch in Programm und Argumente aufgeteilt, und nicht vertrauenswürdiger Text kann die empfangenen Argumente verändern. ProcessBuilder macht die Grenzen explizit; validieren Sie jeden Wert und begrenzen Sie ausführbare Datei und erlaubte Optionen.

RISKANT
// Benutzereingabe wird an den Befehlsstring angehängt
Runtime.getRuntime().exec(
  "approved-tool --input " + filename
);
SICHERER
// Festes Programm und getrennte Argumente; filename zuerst validieren
String safeName = validateFilename(filename);
new ProcessBuilder(
  "/opt/app/bin/approved-tool",
  "--input", safeName
).start();

Shell-Injection und Argument-Injection sind verschieden

Seit Java 18 ist Runtime.exec(String) laut Oracle wegen Fehleranfälligkeit veraltet; empfohlen werden exec(String[]) oder ProcessBuilder. Die String-Überladung zerlegt die Eingabe an Leerraum, wodurch etwa Pfade mit Leerzeichen aufgeteilt werden können. Runtime.exec(String) startet nicht implizit sh oder eine andere Shell; laut Oracle wird die einzelne Zeichenfolge in ein Argument-Array umgewandelt. Übliche Shell-Metazeichen werden dadurch nicht als Shell-Syntax verarbeitet. Das macht Eingaben jedoch nicht sicher: Die Tokenisierung kann weitere Argumente erzeugen, und das Zielprogramm kann ein Argument als Option deuten. ProcessBuilder erhält eine Stringliste aus Programm und Argumenten; auf gängigen Plattformen bildet jedes Element eine Grenze. Halten Sie das Programm fest, validieren Sie Werte nach der erwarteten Grammatik des Zielprogramms und weisen Sie optionsähnliche Werte zurück oder behandeln Sie sie sicher. Verwenden Sie -- nur, wenn die Dokumentation des Programms dies garantiert. Starten Sie mit nicht vertrauenswürdigen Daten keine Shell explizit, etwa über sh -c.

Häufige Fragen

Ist Runtime.exec(String) sicher, weil es keine Shell startet?

Nein. Das verringert das Shell-Injection-Risiko bei dieser Überladung, aber Argument-Injection bleibt möglich. Das Zielprogramm kann Angreifereingaben als Optionen oder Dateinamen interpretieren. Nutzen Sie ProcessBuilder mit festem Programm und getrennten Argumenten und validieren Sie jeden Wert für das Zielprogramm.

Validiert ProcessBuilder die Argumente automatisch?

Nein. Die Klasse baut die Programm- und Argumentliste und startet den Prozess; sie prüft nicht, ob Programm oder Argumente sicher und gültig sind. Verwenden Sie anwendungsseitige Allowlists und Validierung und beachten Sie die dokumentierten Argumentregeln des Programms.

Referenzen

Siehe auch Befehlsinjektion ins Betriebssystem (CWE-78): Funktionsweise und Schutz in jeder Sprache — flawopen.com Command-Injection-Risiko bei Node.js exec() Node.js exec() vs. execFile(): Unterschiede und Sicherheit