Masalahnya adalah dalam kasus di mana konten $xbelum 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 PATHke 2(jalur relatif yang bisa sangat di bawah kendali penyerang). Anda dapat mengganti PATHdengan LD_LIBRARY_PATHatau 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 $xdi beberapa shell yang mengimplementasikan --operator ( opsional sesuai POSIX) (pengurangan) (seperti halnya x=-1, itu berarti meminta shell untuk mengevaluasi 1--1ekspresi aritmatika). "$((1-x))"tidak memiliki masalah seperti xyang diperluas sebagai bagian dari (bukan sebelumnya) evaluasi aritmatika.
In bash, zshand ksh(not dashor yash), if xadalah:
x='a[0$(uname>&2)]'
Kemudian perluasan $((1-$x))atau $((1-x))menyebabkan unameperintah itu dieksekusi (untuk zsh, aperlu variabel array, tetapi orang dapat menggunakan psvarmisalnya 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 bashatau zsh) tetapi juga tergantung pada shell di let, [/ test, declare/typeset/export..., return, break, continue, exit, printf, printbawaan, 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 ( 010kadang-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 diaturPke 8, tetapix='P=3'; : $((x + 5))akan diaturPke3(dalamzsh,kshataubash). "Hal yang sama terjadi dengan$((x + 1))..." tidak benar sekarang; itu akan diaturPATHke2, pada yang lama.