GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie sicher ist die Redewendung `ssh … “$(typeset -f Foo); Foo“`?

Angenommen, eine Shell-Funktion foo wird in der aktuellen Shell-Session definiert. Dann der Befehl

typeset -f foo

gibt den Quellcode dieser Funktion aus. Das bedeutet, dass man diese Funktion zumindest prinzipiell per ssh auf einem entfernten Host ausführen kann wie unten gezeigt:

ssh <REMOTE-HOST> "$(typeset -f foo); foo"

(Für die Zwecke dieser Frage gehen Sie davon aus, dass alle Befehle und Dateisystempfade, die von foo erwähnt werden sind in <REMOTE-HOST> verfügbar . Nehmen Sie außerdem an, dass bash ist die Schale an beiden Enden.)

Mein Instinkt ist, dass die blinde Beschaffung von automatisch generiertem Quellcode wie diesem extrem zerbrechlich wäre, aber ich konnte kein Beispiel für eine Funktion foo finden wo diese Redewendung versagt.

Meine Frage ist:Wie sicher ist diese Redewendung? Wenn es nicht sicher ist, kann mir jemand ein konkretes Beispiel geben, das veranschaulicht, wie es fehlschlägt? (Die Sicherheitsfrage beinhaltet folgendes:tut bash garantieren, dass solche Verwendungen von typeset -f sind sicher?)

Hinweis: In diesem Beitrag suche ich nicht nach Alternativen; Ich möchte nur die Eigenschaften dieses speziellen Idioms verstehen.

BEARBEITEN:klargestellt, dass bash ist die Schale an beiden Enden.

Akzeptierte Antwort:

Es ist nicht sicher, wenn der Code nicht in demselben Gebietsschema interpretiert wird, in dem es generiert wurde (oder wenn das Gebietsschema name ist die gleiche, aber die Definition dieses Gebietsschemas unterscheidet sich zwischen dem ssh-Client-Host und dem Server-Host).

Besonders wichtig ist die Kodierung von Zeichen und die Zugehörigkeit von Zeichen zum blank , alpha und alnum Kategorien.

Zum Beispiel α Zeichen (griechischer Kleinbuchstabe Alpha) im BIG5-Zeichensatz wird als 0xa3 0x5c codiert, wobei 0x5c ist in ASCII (und allen Zeichensätzen einschließlich BIG5).

Wenn Sie also einen foo haben Funktion, die in diesem Zeichensatz definiert ist als:

foo() {
  echo α
}

typeset -f wird es als solches ausgeben, aber wenn es in einem anderen Gebietsschema wie C interpretiert würde, würde dieses 0xa3 0x5c nicht als α genommen werden sondern als unbekanntes 0xa3-Zeichen gefolgt von einem Backslash. Das kann ausgenutzt werden wie mit:

$ env LC_ALL=zh_TW.big5 $'BASH_FUNC_foo%%=() { echo xa3\\;}; echo gotcha; }' bash -c 'typeset -f foo' | bash
gotcha
bash: line 5: syntax error near unexpected token `}'
bash: line 5: `}'

Der foo() { echo α;}; echo gotcha; } wurde foo() { echo <0xa3>\; }; echo gotcha; } wenn sie in einem anderen Gebietsschema interpretiert werden.

Andere Probleme:

Der à Zeichen in UTF-8 wird als 0xc3 0xa0 codiert. In iso8859-1 und mehreren anderen iso8859 Zeichensätze, 0xa0 ist das geschützte Leerzeichen. Auf einigen Systemen ist dieses Zeichen im Leerzeichen enthalten Zeichenklasse, die von der Bash als Token-Trennzeichen in ihrer Syntax geehrt wird.

Verwandt:Linux – Dateiberechtigung nur ausführen?

Solaris ist ein solches System, bei dem U+00A0 als Leerzeichen betrachtet wird:

$ env $'BASH_FUNC_foo%%=() { nawk -v x=àBEGIN'{system("echo gotcha")}' 1;}' bash -c 'typeset -f foo; echo foo'  | ssh solaris LC_ALL=en_GB.ISO8859-1 bash
gotcha

Sehen Sie, wie die:

nawk -v x=àBEGIN... 1

wurde interpretiert als:

nawk -v x=<0xc3> 'BEGIN{system("...")}' 1

Beachten Sie, dass, wenn die Funktion in einem Gebietsschema definiert wurde, in dem 0xa0 kein Leerzeichen war oder in dem 0xa3 0x5c Alpha war, typeset -f wird es immer noch gleich ausgeben, selbst wenn es in einem Gebietsschema aufgerufen wird, in dem es ein Leerzeichen ist (erzeugt eine andere Ausgabe, wenn es interpretiert wird)

$ LC_ALL=zh_TW.big5 bash -c $'f() { echo xa3x5c$(uname); }; export LC_ALL=C; typeset -f f | bash'
bash: line 3: syntax error near unexpected token `('
bash: line 3: `    echo �$(uname)'

Allgemeiner gesagt, die Ausgabe von typeset , alias , export -p , set , locale sind alle gemeint für die Neueingabe in eine Shell geeignet sein, aber abgesehen von diesen Gebietsschemaproblemen sind verschiedene Implementierungen dafür bekannt, dass sie mehrere Probleme haben, und ich wäre nicht überrascht, wenn es noch viele weitere gäbe.

Also, ja, ich stimme zu, dass Sie es zu Recht für gefährlich halten, und es ist eine gute Idee, sie nur in einem Kontext zu verwenden, in dem Sie wissen, woher die ausgegebenen Daten stammen. Zum Beispiel im Fall von typeset -f foo , verwenden Sie es nur auf einem foo Funktion, die Sie definiert haben (und vermeiden Sie die Verwendung von Nicht-ASCII-Zeichen darin).


Linux
  1. Der Zweck von .bashrc und wie funktioniert es?

  2. Wie stoppe ich das Loop Bash-Skript im Terminal?

  3. Ist Rsync ~/foo Target/foo dasselbe wie Rsync ~/foo/Target/foo/?

  4. Wie liest man das gesamte Shell-Skript, bevor man es ausführt?

  5. Wie liest man die vorletzte Zeile in einer Datei mit Bash?

So verwenden Sie den Bash-Let-Befehl {mit Beispielen}

So verwenden Sie den Bash-Lesebefehl

Wie erhalte ich das absolute Verzeichnis einer Datei in Bash?

Wie stelle ich die Farbe der Eingabeaufforderung in Bash ein?

Wie finde ich den Index eines Wortes in einer Zeichenfolge in Bash?

Wie ändere ich schnell das erste Wort in einem Bash-Befehl?