Das Problem tritt in Fällen auf, in denen der Inhalt von $x
nicht 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 PATH
auf 2
(ein relativer Pfad, der sehr gut vom Angreifer kontrolliert werden kann) erfolgt. Sie können PATH
mit LD_LIBRARY_PATH
oder 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 $x
einiger Shells, die den (optionalen nach POSIX) --
(Dekrement) -Operator implementieren, funktioniert dies nicht ordnungsgemäß (wie bei x=-1
, dh, die Shell wird aufgefordert, den 1--1
arithmetischen Ausdruck auszuwerten ). "$((1-x))"
hat das Problem nicht, da x
es im Rahmen (nicht vor) der arithmetischen Auswertung erweitert wird.
In bash
, zsh
und ksh
(nicht dash
oder yash
), wenn x
ist:
x='a[0$(uname>&2)]'
Dann wird die Expansion der $((1-$x))
oder $((1-x))
bewirkt , dass uname
Befehl ausgeführt werden (z zsh
, a
muss ein Array variabel sein, aber man kann verwendet werden psvar
beispielsweise 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 bash
oder zsh
) , sondern auch in Abhängigkeit von der Schale in der let
, [
/ test
, declare/typeset/export...
, return
, break
, continue
, exit
, printf
, print
Builtins, 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 ( 010
manchmal 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 eingestelltP
bis 8, aberx='P=3'; : $((x + 5))
wird eingestellt ,P
um3
(inzsh
,ksh
oderbash
). "Das gleiche passiert mit$((x + 1))
..." ist jetzt nicht richtig; es wird festgelegt ,PATH
um2
, wie in alten Zeiten .