Masalahnya adalah dalam kasus di mana konten $x
belum disanitasi dan berisi data yang berpotensi berada di bawah kendali penyerang dalam kasus kode shell mungkin akhirnya digunakan dalam konteks eskalasi hak istimewa (misalnya skrip yang dipanggil oleh setuid aplikasi, skrip sudoers atau digunakan untuk memproses data di luar jaringan (CGI, DHCP hook ...) secara langsung atau tidak langsung).
Jika:
x='(PATH=2)'
Kemudian:
x=$((1-$x)))
memiliki efek samping pengaturan PATH
ke 2
(jalur relatif yang bisa sangat di bawah kendali penyerang). Anda dapat mengganti PATH
dengan LD_LIBRARY_PATH
atau IFS
... Hal yang sama terjadi dengan x=$((1-x))
di bash, zsh atau ksh (bukan dash atau yash yang hanya menerima konstanta numerik dalam variabel di sana).
Perhatikan bahwa:
x=$((1-$x))
tidak akan berfungsi dengan baik untuk nilai negatif $x
di beberapa shell yang mengimplementasikan --
operator ( opsional sesuai POSIX) (pengurangan) (seperti halnya x=-1
, itu berarti meminta shell untuk mengevaluasi 1--1
ekspresi aritmatika). "$((1-x))"
tidak memiliki masalah seperti x
yang diperluas sebagai bagian dari (bukan sebelumnya) evaluasi aritmatika.
In bash
, zsh
and ksh
(not dash
or yash
), if x
adalah:
x='a[0$(uname>&2)]'
Kemudian perluasan $((1-$x))
atau $((1-x))
menyebabkan uname
perintah itu dieksekusi (untuk zsh
, a
perlu variabel array, tetapi orang dapat menggunakan psvar
misalnya untuk itu).
Singkatnya, orang tidak boleh menggunakan uninitialised atau non-disterilkan data eksternal dalam ekspresi aritmatika pada kulit (catatan bahwa evaluasi aritmatika dapat dilakukan oleh $((...))
(alias $[...]
di bash
atau zsh
) tetapi juga tergantung pada shell di let
, [
/ test
, declare/typeset/export...
, return
, break
, continue
, exit
, printf
, print
bawaan, indeks array, ((..))
dan[[...]]
konstruksi untuk beberapa nama).
Untuk memeriksa apakah suatu variabel berisi angka integer desimal literal, Anda dapat menggunakan POSIXly:
case $var in
("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac
Berhati-hatilah karena [0-9]
di beberapa lokal cocok dengan lebih dari 0123456789.[[:digit:]]
harus OK tapi saya tidak akan bertaruh.
Juga ingat bahwa angka-angka dengan nol di depan diperlakukan sebagai oktal dalam beberapa konteks ( 010
kadang-kadang 10, kadang-kadang 8) dan berhati-hatilah bahwa pemeriksaan di atas akan membiarkan angka-angka yang berpotensi lebih besar daripada bilangan bulat maksimum yang didukung oleh sistem Anda (atau aplikasi apa pun yang Anda inginkan) gunakan integer itu di; bash misalnya memperlakukan 18446744073709551616 sebagai 0 karena itu 2 64 ). Jadi, Anda mungkin ingin menambahkan cek tambahan dalam pernyataan kasus di atas seperti:
(0?* | -0?*)
echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;
Contoh:
$ 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
Lebih banyak membaca di:
x='P=3'; : $(($x + 5))
akan diaturP
ke 8, tetapix='P=3'; : $((x + 5))
akan diaturP
ke3
(dalamzsh
,ksh
ataubash
). "Hal yang sama terjadi dengan$((x + 1))
..." tidak benar sekarang; itu akan diaturPATH
ke2
, pada yang lama.