Innerhalb einer Programmiersprache führe ich einen einfachen Shell-Befehl aus
cd var; echo > create_a_file_here
Dabei ist var eine Variable, die eine Zeichenfolge (hoffentlich) eines Verzeichnisses an der Stelle enthält, an der ich die Datei "create_a_file_here" erstellen möchte. Wenn jemand diese Codezeile sieht, kann er ausgenutzt werden, indem beispielsweise Folgendes zugewiesen wird:
var = "; rm -rf /"
Die Dinge können ziemlich hässlich werden. Eine Möglichkeit, den obigen Fall zu vermeiden, besteht darin, die Zeichenfolge in var nach Sonderzeichen wie ';' zu durchsuchen. vor dem Ausführen des Shell-Befehls, aber ich bezweifle, dass dies alle möglichen Exploits abdeckt.
Kennt jemand einen guten Weg, um sicherzustellen, dass "cd var" nur ein Verzeichnis ändert und sonst nichts?
shell-script
shell
ES___
quelle
quelle
var
als Argument übergeben. ZB der Aufrufsh
mit Argumenten-c
,'cd "$1"; echo > create_a_file_here'
,'sh'
,var
Arbeiten und benötigt keine Änderungenvar
. Das'sh'
Argument wird als übergeben$0
.sh
oder erstellen Sie eine eigene Programmiersprache mit einer ähnlichen Syntax, die jedoch erweitert wird,var
anstatt dass Sie schreiben müssencd "$var"
? Oder ist dasbash
mitshopt -s cdable_vars
? Oh, ich denke du meinst, dass ein anderes Programm eine Shell zwingt, um diese Befehle auszuführen. Also zitieren Sie einfachvar
, aber stellen Sie sicher, dass es kein Anführungszeichen selbst enthält ...s='"'; echo "$s"
Drucke"
.var=untrusted string
im übergeordneten Programm, ebensovar
wie eine Umgebungsvariable, die bereits beim Aufrufen festgelegt wurdesh
. Dann müssen Sie es nur jedes Mal zitieren, wenn Sie es erweitern, was zuverlässig möglich ist. Ah, ich sehe , dass Idee ist bereits Teil von Stéphane Antwort> <.Antworten:
Wenn ich richtig verstehe,
var
ist eine Variable in Ihrer Programmiersprache.In Ihrer Programmiersprache fordern Sie eine Shell auf, eine Zeichenfolge zu interpretieren, die die Verkettung
"cd "
, den Inhalt dieser Variablen und darstellt"; echo > create_a_file_here"
.Wenn dann, ja, wenn der Inhalt von
var
nicht streng kontrolliert wird, handelt es sich um eine Sicherheitsanfälligkeit bezüglich Befehlsinjektion.Sie können versuchen, den Inhalt der Variablen¹ in der Syntax der Shell korrekt in Anführungszeichen zu setzen, damit sie garantiert als einzelnes Argument an das integrierte
cd
Element übergeben wird.Ein anderer Ansatz wäre, den Inhalt dieser Variablen auf eine andere Weise zu übergeben. Ein naheliegender Weg wäre, dies in einer Umgebungsvariablen zu übergeben. Zum Beispiel in C:
Dieses Mal ist der Code, den Sie von der Shell zur Interpretation auffordern, behoben. Wir müssen ihn weiterhin ordnungsgemäß in die Syntax der Shell schreiben (hier wird angenommen, dass es sich um eine POSIX-kompatible Shell handelt):
-P
fürcd
eine einfache tunchdir()
--
das Ende der Optionen markieren, um Probleme beimvar
Starten mit-
(oder+
in einigen Shells) zu vermeiden.CDPATH
auf die leere Zeichenfolge, falls sie sich in der Umgebung befindetecho
Befehl nur aus, wenn ercd
erfolgreich war.Es gibt (mindestens) ein verbleibendes Problem: Wenn dies der Fall
var
ist-
, wird das Verzeichnis nicht in das aufgerufene Verzeichnis,-
sondern in das vorherige Verzeichnis (wie darin gespeichert$OLDPWD
) verschoben und esOLDPWD=- CDPATH= cd -P -- "$DIR"
wird nicht garantiert , dass es umgeht . Sie brauchen also etwas wie:¹ Beachten Sie, dass
es nicht der richtige Weg ist , nur a zu tun. Sie würden das Problem nur verschieben.system(concat("cd \"", var, "\"; echo..."));
Zum Beispiel
var = "$(rm -rf /)"
wäre a immer noch ein Problem.Die einzige zuverlässige Möglichkeit, Text für Bourne-ähnliche Shells in Anführungszeichen zu setzen, besteht darin, einfache Anführungszeichen zu verwenden und sich auch um die einfachen Anführungszeichen zu kümmern, die in der Zeichenfolge auftreten können. Wenden Sie sich zum Beispiel
char *var = "ab'cd"
an achar *escaped_var = "'ab'\\''cd'"
. Das heißt, ersetzen Sie alle'
zu'\''
und wickeln Sie das Ganze innen'...'
.Das setzt voraus , dass nach wie vor , dass Zeichenfolge in Anführungszeichen nicht innerhalb von Backticks verwendet wird, und Sie würden immer noch brauchen die
--
,-P
,&&
,CDPATH=
...quelle
Einfache Lösung: Rufen Sie die Shell nicht aus Ihrem Programm auf. Überhaupt.
Ihr Beispiel hier ist trivial. Das Ändern des Verzeichnisses und das Erstellen von Dateien sollte in jeder Programmiersprache einfach sein. Aber selbst wenn Sie einen externen Befehl ausführen müssen, ist dies normalerweise nicht über die Shell erforderlich.
Also, zB in Python, anstatt zu laufen
os.system("somecmd " + somearg)
, verwendensubprocess.run(["somecmd", somearg])
.system()
Verwenden Sie in C stattdessenfork()
undexec()
(oder suchen Sie eine Bibliothek, die dies tut).Wenn Sie die Shell verwenden müssen, zitieren Sie die Befehlszeilenargumente oder übergeben Sie sie wie in Stéphanes Antwort an die Umgebung . Auch, wenn Sie finden sich Sorgen Sie sich über Sonderzeichen, die richtige Lösung ist, nicht zu versuchen , heraus zu filtern (schwarze Liste) potenziell gefährliche Zeichen, sondern nur zu halten bekannte Zeichen sicher zu sein (Whitelist).
Lassen Sie nur die Zeichen zu, deren Funktionen Sie kennen. Auf diese Weise besteht ein geringeres Risiko, dass etwas fehlt. Das Endergebnis könnte sein, dass Sie sich nur dafür entscheiden, es zuzulassen
[a-zA-Z0-9_]
, aber das könnte gerade ausreichen, um die Arbeit zu erledigen. Möglicherweise möchten Sie auch überprüfen, ob Ihr Gebietsschema und Ihr Toolset keine Buchstaben mit Akzent wieä
undö
darin enthalten. Sie werden wahrscheinlich von keiner Shell als besonders angesehen, aber auch hier ist es besser, sicher zu sein, ob sie passen oder nicht.quelle
[a-zA-Z0-9]
verwenden, keine Dinge enthält,à
deren Codierung auch von einigen Shells (wiebash
) in einigen Gebietsschemas falsch interpretiert werden könnte .Innerhalb einer Programmiersprache sollte es bessere Möglichkeiten geben, als Shell-Befehle auszuführen. Wenn Sie beispielsweise durch
cd var
das Äquivalent Ihrer Programmiersprache ersetzen,chdir (var);
sollte sichergestellt werden, dass jeder Trick mit dem Wert "var
nur" zu einem Fehler "Verzeichnis nicht gefunden" führt und nicht zu unbeabsichtigten und möglicherweise böswilligen Aktionen.Sie können auch absolute Pfade verwenden, anstatt Verzeichnisse zu ändern. Verketten Sie einfach den Verzeichnisnamen, den Schrägstrich und den Dateinamen, den Sie verwenden möchten.
In C könnte ich so etwas tun:
Sicher kann Ihre Programmiersprache etwas Ähnliches tun?
quelle