Последствия безопасности использования несанированных данных в оценке Арифметики Shell

Это работает на Вас?

date -d "-1 month -$(($(date +%d)-1)) days" "+%a %b %d 00:00:00 %Z %Y"
date -d "-$(date +%d) days -0 month" "+%a %b %d 23:59:59 %Z %Y"
19
13.04.2017, 15:36
1 ответ

Проблема заключается в тех случаях, когда содержимое $ x не было очищено и содержит данные, которые потенциально могут находиться под контролем злоумышленника в случаях, когда код оболочки может в конечном итоге использоваться с привилегиями контекст эскалации (например, сценарий, вызываемый приложением setuid, сценарий sudoers или используемый для обработки данных вне сети (CGI, DHCP-перехватчик ...) прямо или косвенно).

Если:

x='(PATH=2)'

То:

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

имеет побочный эффект установки ПУТЬ на 2 (относительный путь, который вполне может быть под контролем злоумышленника). Вы можете заменить PATH на LD_LIBRARY_PATH или IFS ... То же самое происходит с x = $ ((1-x)) в bash, zsh или ksh (не тире и не yash, которые принимают только числовые константы в переменных).

Обратите внимание, что:

x=$((1-$x))

не будет работать должным образом для отрицательных значений $ x в некоторых оболочках, которые реализуют (необязательный согласно POSIX) оператор - (декремент) (как и в случае x = -1 , это означает, что оболочка должна вычислить арифметическое выражение 1–1 ). «$ ((1-x))» не имеет проблемы, поскольку x раскрывается как часть (не раньше) арифметической оценки.

В bash , zsh и ksh (не тире или yash ), если x :

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

Тогда расширение $ ((1- $ x)) или $ ((1-x)) приводит к тому, что uname , которая должна быть выполнена (для zsh , a должен быть переменной массива, но, например, для этого можно использовать psvar ).

Таким образом, не следует использовать неинициализированные или незащищенные внешние данные в арифметических выражениях в оболочках (обратите внимание, что арифметические вычисления могут быть выполнены с помощью $ ((...)) (также известного как ] $ [...] в bash или zsh ), но также в зависимости от оболочки в let , [ / test , declare / typeset / export ... , return , break , continue , ] exit , printf , print встроенные функции, индексы массивов, ((..)) и [[...]] и многие другие).

Чтобы проверить, что переменная содержит буквальное десятичное целое число, вы можете использовать POSIXly:

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

Помните, что [0-9] в некоторых регионах соответствует более чем 0123456789. [[: digit:]] должно быть в порядке, но я бы не стал на это делать ставку.

Также помните, что числа с ведущими нулями в некоторых контекстах рассматриваются как восьмеричные ( 010 иногда равно 10, иногда 8), и имейте в виду, что приведенная выше проверка позволит пропускать числа, которые потенциально больше максимального целого поддерживается вашей системой (или любым другим приложением, в котором вы будете использовать это целое число; например, bash обрабатывает 18446744073709551616 как 0 как 2 64 ). Таким образом, вы можете добавить дополнительные проверки в этот оператор case выше, например:

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

Примеры:

$ 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

Дополнительная информация по адресу:

24
27.01.2020, 19:45

Теги

Похожие вопросы