Sicherheit Auswirkungen der Verwendung nicht bereinigter Daten in der Shell Arithmetic-Auswertung


17

In einem Kommentar zu einer kürzlich gestellten Frage erwähnt Stéphane Chazelas, dass doppelte Klammern Auswirkungen auf die Sicherheit haben, z.

x=$((1-$x))

auf den meisten Muscheln.

Meine Google-Kenntnisse scheinen verrostet zu sein und ich kann nichts finden. Welche Sicherheitsrisiken ergeben sich aus der Doppelklammer-Arithmetik?

Antworten:


22

Das Problem tritt in Fällen auf, in denen der Inhalt von $xnicht bereinigt wurde und Daten enthält, die möglicherweise von einem Angreifer kontrolliert werden können, wenn Shell-Code möglicherweise in einem Kontext der Rechteerweiterung verwendet wird (z. B. ein Skript, das von einer Setuid aufgerufen wird) Anwendung, ein Sudoers-Skript oder zur direkten oder indirekten Verarbeitung von Daten außerhalb des Netzwerks (CGI, DHCP-Hook ...).

Wenn:

x='(PATH=2)'

Dann:

x=$((1-$x)))

hat den Nebeneffekt, dass die Einstellung PATHauf 2(ein relativer Pfad, der sehr gut vom Angreifer kontrolliert werden kann) erfolgt. Sie können PATHmit LD_LIBRARY_PATHoder IFS... ersetzen. Dasselbe gilt x=$((1-x))für bash, zsh oder ksh (weder Bindestrich noch Yash, die dort nur numerische Konstanten in Variablen akzeptieren).

Beachten Sie, dass:

x=$((1-$x))

Bei negativen Werten $xeiniger Shells, die den (optionalen nach POSIX) --(Dekrement) -Operator implementieren, funktioniert dies nicht ordnungsgemäß (wie bei x=-1, dh, die Shell wird aufgefordert, den 1--1arithmetischen Ausdruck auszuwerten ). "$((1-x))"hat das Problem nicht, da xes im Rahmen (nicht vor) der arithmetischen Auswertung erweitert wird.

In bash, zshund ksh(nicht dashoder yash), wenn xist:

x='a[0$(uname>&2)]'

Dann wird die Expansion der $((1-$x))oder $((1-x))bewirkt , dass unameBefehl ausgeführt werden (z zsh, amuss ein Array variabel sein, aber man kann verwendet werden psvarbeispielsweise für die).

Zusammenfassend sollte man nicht uninitialised oder nicht hygienisiert externe Daten in arithmetischen Ausdrücken in Schalen (Anmerkung verwenden , die arithmetische Auswertung durch getan werden kann $((...))(auch bekannt als $[...]in bashoder zsh) , sondern auch in Abhängigkeit von der Schale in der let, [/ test, declare/typeset/export..., return, break, continue, exit, printf, printBuiltins, Array-Indizes ((..))und [[...]]Konstrukte, um nur einige zu nennen.

Mit POSIXly können Sie überprüfen, ob eine Variable eine literalen Dezimalzahl enthält:

case $var in
  ("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac

Beachten Sie, dass [0-9]in einigen Ländereinstellungen mehr als 0123456789 vorhanden sein [[:digit:]]sollte, aber ich würde nicht darauf wetten.

Denken Sie auch daran, dass Zahlen mit führenden Nullen in einigen Kontexten ( 010manchmal 10, manchmal 8) als oktal behandelt werden , und achten Sie darauf, dass bei der obigen Prüfung Zahlen durchgelassen werden, die möglicherweise größer sind als die maximale Ganzzahl, die von Ihrem System (oder einer anderen Anwendung) unterstützt wird verwenden, um diese ganze Zahl in; bash etwa behandelt 18446744073709551616 als 0 , wie die 2 ist 64 ). Vielleicht möchten Sie in der obigen case-Anweisung zusätzliche Prüfungen hinzufügen, z.

(0?* | -0?*)
  echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
  echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;

Beispiele:

$ export 'x=psvar[0$(uname>&2)]'
$ ksh93 -c 'echo "$((x))"'
Linux
ksh93: psvar: parameter not set
$ ksh93 -c '[ x -lt 2 ]'
Linux
ksh93: [: psvar: parameter not set
$ bash -c 'echo "$((x))"'
Linux
0
$ bash -c '[[ $x -lt 2 ]]'
Linux
$ bash -c 'typeset -i a; export a="$x"'
Linux
$ bash -c 'typeset -a a=([x]=1)'
Linux
$ bash -c '[ -v "$x" ]'
Linux
$ mksh -c '[[ $x -lt 2 ]]'
Linux
$ zsh -c 'echo "$((x))"'
Linux
0
$ zsh -c 'printf %d $x'
Linux
0
$ zsh -c 'integer x'
Linux
$ zsh -c 'exit $x'
Linux

Lesen Sie mehr unter:


x='P=3'; : $(($x + 5))wird eingestellt Pbis 8, aber x='P=3'; : $((x + 5))wird eingestellt , Pum 3(in zsh, kshoder bash). "Das gleiche passiert mit $((x + 1))..." ist jetzt nicht richtig; es wird festgelegt , PATHum 2, wie in alten Zeiten .
Mosvy

@mosvy, richtig danke (und für deine frühere Bearbeitung). Korrigiert jetzt.
Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.