Существуют ли проблемы безопасности при использовании eval для переменной среды в сценарии bash? - PullRequest
0 голосов
/ 16 марта 2020

У меня есть сценарий Bash, в котором я вызываю rsync для выполнения резервного копирования на удаленный сервер. Чтобы указать, что резервная копия моей папки «Загрузки», я передаю "'${HOME}/Downloads'" в качестве аргумента rsync, который выдает:

rsync -avu '/Volumes/Norman Data/Downloads' me@example.com:backup/

Выполнение команды с переменной, расширенной, как указано выше (через терминал или в скрипте) работает нормально, но из-за пробела в раскрытой переменной и того факта, что кавычки (одиночные тики) игнорируются при включении в переменную, передаваемую как часть аргумента (см. здесь ), единственный способ, которым я могу заставить его не задыхаться в пространстве, это сделать:

stmt="rsync -avu '${HOME}/Downloads' me@examle.com:backup/"
eval ${stmt}

Похоже, что при запуске eval будут присутствовать некоторые уязвимости на всем, что не на 100% приватно для этот сценарий. Правильно ли я считаю, что должен поступать иначе? Если это так, любые советы для bash начинающего сценария будут с благодарностью.


** РЕДАКТИРОВАТЬ ** - у меня действительно есть немного более сложный вариант использования, чем. пример выше. Для пройденных путей у меня есть массив из них, каждый из которых содержит пробелы, которые я затем объединяю в 1 строковый вид вроде

include_paths=(
  "'${HOME}/dir_a'"
  "'${HOME}/dir_b' --exclude=video"
)

for item in "${include_paths[@]}"
  do
    inc_args="${inc_args}" ${item}
  done

inc_args, оцениваемый в '/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video

который я затем пытаюсь передать в качестве аргумента rsync, но одиночные тики читаются как литералы, и после 1-го /Volumes/Norman он разрывается из-за пробела.

rsync -avu "${inc_args}" me@example.com:backup/

Использование eval похоже на чтение одиночные галочки как кавычки и выполняются:

rsync -avu '/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video me@example.com:backup/

, как мне нужно. Кажется, я не могу найти другой способ работы.


** РЕДАКТИРОВАТЬ 2 - РЕШЕНИЕ **
Итак, первое, что я нужно было изменить массив include_paths на:

  • убрать одиночные галочки из элементов в двойных кавычках
  • переместить любые флаги с указанием пути c флаги (например, --exclude ) к своим собственным элементам непосредственно после пути, который должен применяться к

Затем я создал массив, содержащий команду rsync и ее параметры, добавил расширенные массивы include_paths и exclude_paths и строка подключения к удаленному хосту.

И, наконец, расширил этот массив, в котором выполнялась вся моя, правильно указанная команда rsync. В конце концов, модифицированный массив include_paths имеет вид:

include_paths=(
  "${HOME}/dir_a"
  "${HOME}/dir_b"
  "--exclude=video"
  "${HOME}/dir_c"
)

, и я собрал все вместе с:

cmd=(rsync -auvzP)
for item in "${exclude_paths[@]}"
  do  
    cmd+=("--exclude=${item}")
  done

for item in "${include_paths[@]}"
  do
   cmd+=("${item}")
  done

cmd+=("me@example.com:backup/")

set -x
"${cmd[@]}"

1 Ответ

2 голосов
/ 16 марта 2020

Используйте массив для команд / опции вместо простой переменной.

stmt=(rsync -avu "${HOME}/Dowloads" me@example.com:backup/)

Выполните его с помощью встроенного command

command "${stmt[@]}"

... Или я лично просто поместите параметры / аргументы в массив.

options=(-avu "${HOME}/Download" me@example.com:backup/)

Выполните его, используя rsync

rsync "${options[@]}"

Если у вас есть более новая версия bash, которая поддерживает дополнительное расширение параметра PE, тогда вы, вероятно, могли бы заключить в кавычки массив.

options=(-avu "${HOME}/Download" me@example.com:backup/)

Проверьте вывод, применив PE

echo "${options[@]@Q}"

Следует напечатать

'-avu' '/Volumes/Norman Data/Downloads' 'me@examle.com:backup/'

Тогда Вы можете просто

rsync "${options[@]@Q}"

...