Sorun, içeriğinin $x
sterilize edilmemiş olması ve kabuk kodunun bir ayrıcalık yükselmesi bağlamında (örneğin, bir setuid tarafından çağrılan bir komut dosyası) kullanılabileceği durumlarda, saldırganın kontrolü altında olabilecek verileri içerdiği durumlarda uygulama, bir sudoers betiği veya doğrudan veya dolaylı olarak ağ dışı verileri (CGI, DHCP kancası ...) işlemek için kullanılır.
Eğer:
x='(PATH=2)'
Sonra:
x=$((1-$x)))
ayarlayarak yan etkisi yoktur PATH
için 2
(çok iyi saldırganın denetimindeki olabilir göreli yol). Sen yerini alabilir PATH
ile LD_LIBRARY_PATH
veya IFS
aynı ile olur ... x=$((1-x))
(çizgi ne de sadece orada değişkenlerde sayısal sabitleri kabul yash değil) bash, zsh veya ksh.
Bunu not et:
x=$((1-$x))
$x
(POSIX uyarınca isteğe bağlı) --
(azaltma) operatörünü uygulayan bazı kabuklardaki negatif değerler için düzgün çalışmaz (olduğu gibi x=-1
, kabuktan 1--1
aritmetik ifadeyi değerlendirmesini istemek anlamına gelir ). aritmetik değerlendirmenin bir parçası olarak (daha önce değil) genişletildiği "$((1-x))"
için sorun x
yoktur.
In bash
, zsh
ve ksh
(değil dash
ya yash
), eğer x
geçerli:
x='a[0$(uname>&2)]'
Daha sonra bu komutun genişletilmesi $((1-$x))
veya yürütülmesine $((1-x))
neden olur uname
(için zsh
, a
bir dizi değişkeni olması gerekir, ancak psvar
bunun için örneğin kullanılabilir ).
Özet olarak, bir uninitialised kullanmak gerekir ve aritmetik değerlendirme yapılabilir, dış kabuklar aritmetik ifadelerde veri (not olmayan temizlenmiş $((...))
(aka $[...]
içinde bash
ya da zsh
), ancak aynı zamanda kabuk bağlı olarak let
, [
/ test
, declare/typeset/export...
, return
, break
, continue
, exit
, printf
, print
buildins, array indeksleri ((..))
ve builds [[...]]
birkaç isim).
Bir değişkenin değişmez ondalık tam sayı içerdiğini kontrol etmek için POSIXly kullanabilirsiniz:
case $var in
("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac
[0-9]
Bazı yerel maçlarda 0123456789'dan fazla eşleştiğine dikkat edin. [[:digit:]]
Tamam olmalı ama üzerine bahis oynamam.
Ayrıca, önde gelen sıfırları olan sayıların bazı bağlamlarda sekizli olarak ele alındığını ( 010
bazen 10, bazen 8'dir) ve yukarıdaki kontrolün, sisteminiz tarafından desteklenen maksimum tamsayıdan (veya istediğiniz herhangi bir uygulamadan) potansiyel olarak daha büyük olan sayılara izin vereceğini unutmayın. bu tamsayıyı kullanın; örneğin bash, 18446744073709551616'yı 0 olarak 2 64 gibi davranır ). Dolayısıyla, yukarıdaki bu durum ifadesine aşağıdaki gibi ek denetimler eklemek isteyebilirsiniz:
(0?* | -0?*)
echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;
Örnekler:
$ 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
Daha fazla okuma:
x='P=3'; : $(($x + 5))
ayarlayacaktırP
8'e fakatx='P=3'; : $((x + 5))
ayarlarP
için3
(içindezsh
,ksh
ya dabash
). "Aynı şey$((x + 1))
... ile de şimdi doğru değil; o koyacaktırPATH
için2
eski itibariyle.