Kann mir bitte jemand erklären warum man eine Shell vermeiden sollte, sprich subprocess.Popen() anstatt os.system() verwenden soll? Welche Gründe außer Quoting gibt es noch?
Ist rein interessehalber, hab aber nirgends was genaues und ausführliches gefunden. Schonmal im Voraus vielen Dank!
warum subprocess.Popen() anstatt os.system()?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Neben dem angeführten Quoting sparst du dir auch noch den Aufruf einer zusätzlichen Shell die du gar nicht brauchst. Noch dazu bietet subprocess unter einem einheitlichen Interface eben alles mögliche was mit Kommunikation mit Prozessen nötig ist, statt es in os, os.popen* und popen2 zu verstreuen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
So:snafu hat geschrieben:Und bei os.sytem soll man Schadcode einfügen können, was bei subprocess angeblich nicht möglich ist. Wie das genau funktioniert, habe ich allerdings auch noch nicht verstanden.
Code: Alles auswählen
$ ls this_will_be_removed
this_will_be_removed
$ cat less.py
import os
import sys
os.system('less %s' % raw_input('filename: '))
$ python less.py
filename: less.py; rm this_will_be_removed
$ ls this_will_be_removed
ls: Zugriff auf this_will_be_removed nicht möglich: No such file or directory
Man kann das über Whitelists, Blacklists oder Escaping verhindern, man kann aber auch einfach subprocess nutzen, was den Argumentvektor über "execlvp" direkt befüllt, und somit erst gar nicht anfällig dafür ist.
Außerdem ermöglicht das z.B. IFS-Angriffe: Bei manchen Unix-Shells wird $IFS bei der Shell-Initialisierung nicht initialisiert, sondern aus der Umgebung des Vater-Prozesses übernommen. Man kann also vor dem Kommando $IFS auf '/' setzen und exportieren, was dann dazu führt, dass dann der absolute Pfad des Kommandos geteilt wird, und der erste Bestandteil als im $PATH gesucht wird. Das wäre dann eine Art indirekter Shell Injection, die auch ohne Nutzereingabe funktioniert. Moderne Shells setzen $IFS aber zurück, so dass das unter Linux nicht mehr klappt.
Im Übrigen spart die Nutzung von "subprocess" auch einen fork/exec-Schritt, was der Performance nur zuträglich sein kann.
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Schade, hättest du jetzt "... und somit erst gar keinen Angriffsvektor zulässt" geschrieben, hättest du einen Satz gehabt, mit dem du jeden Mathematiker in den Wahnsinn treiben kannst...lunar hat geschrieben: Man kann das über Whitelists, Blacklists oder Escaping verhindern, man kann aber auch einfach subprocess nutzen, was den Argumentvektor über "execlvp" direkt befüllt, und somit erst gar nicht anfällig dafür ist.
"system()" ist eine POSIX-Funktion, die immer die POSIX-Shell unter "/bin/sh" aufruft. Auf allen halbwegs POSIX-kompatiblen Systemen verhält sich "system()" immer gleich. Das betrifft eigentlich jedes Unix, und auch Linux.nummer9 hat geschrieben:Außerdem kann es vorkommen, dass der Benutzer z.B. eine exotische Shell hat oder gar keine und somit os.system nicht funktioniert.
Windows mit seinem Shell-Verschnitt tanzt natürlich aus der Reihe, aber im Unix-Universum ist "system()" plattformübergreifend.