Вопрос или проблема
Я пишу shell скрипт, который изменяет свое поведение в зависимости от количества переданных позиционных параметров
script.sh
if [ $# -eq 1 ]; then
if [ -f "$1" ]; then
validate="validate <"$1""
else
validate="validate <<<"$1""
fi
else
IFS=$'\n'
validate="validate <<<'${*}'"
fi
eval "$validate" | pull_data
И validate
, и pull_data
— это функции Bash, которые читают из stdin и пишут в stdout
Если первый случай [ $# -eq 1 ]
, я считаю, что код безопасен от инъекций. Поскольку строка находится в одинарных кавычках, расширение параметра происходит только после вызова eval. Я не могу придумать строку, которая могла бы привести к инъекции кода здесь.
Проблема
Проблема возникает с условием else
. Здесь каждый позиционный параметр расширяется в новую строку. Например
./script.sh "string_with_'_in_its_name" "code injected'"
Кавычка внутри одного из первых параметров вызывает интерпретацию последующих новых параметров как команд. Аналогично это также приводит к уязвимости инъекции:
./script.sh valid_input \''$(code injected)'\'
Контекст
Я использую eval, чтобы избежать повторения конструкции validate ... | pull_data
в каждом условии if. Настоящий скрипт имеет гораздо больше условий, и использование eval делает его более читаемым.
Любые советы о том, как переработать этот скрипт, чтобы избежать проблемы инъекции при сохранении удобочитаемости, будут очень признательны!
Ответ или решение
Чтобы обеспечить безопасность использования команды eval
в вашем скрипте, очень важно принимать меры предосторожности для предотвращения возможности инъекций кода. Проблемы, которые вы описали, действительно могут привести к уязвимостям, если использовать eval
небезопасно. Давайте разберемся, как можно решить эти проблемы, сохраняя читаемость вашего скрипта.
Проблема
Использование eval
приводит к выполнению строки как команды в оболочке. В вашем скрипте это может вызвать уязвимость, если параметры могут не так интерпретироваться, как ожидалось. В частности, когда вы передаете параметры, содержащие специальные символы или апострофы, это может привести к инъекции кода.
Решение
-
Избегайте использования
eval
, если это возможно. Попробуйте изменить архитектуру скрипта так, чтобыeval
не использовался вовсе. Например, вместо динамического построения строки сeval
, вы можете использовать функции или прямую проверку условий и вызов нужных функций. -
Используйте массивы. Если вы вынуждены использовать
eval
из-за архитектуры кода, используйте массивы и безопасные функции обработки строк. Массивы позволяют сохранить параметры скрипта, избегая необходимости вeval
. -
Более безопасные альтернативы. Для аналогичной функциональности можно использовать
xargs
илиset
для безопасного управления параметрами. Это позволяет избежать необходимости использоватьeval
для обработки изменений параметров. -
Экранирование параметров. Убедитесь, что все параметры, передаваемые в
eval
, тщательно экранируются, чтобы избежать интерпретации нежелательных символов как команд оболочки. Однако следует заметить, что экранирование не всегда может защитить от всех возможных уязвимостей, особенно когда речь идет о сложных строках. -
Контекстуальная проверка. Добавьте строгие проверки входных данных на этапе валидации. Разработайте алгоритм для проверки каждого параметра функции
validate
до того, как она попадет вeval
.
Рефакторинг
Ваш скрипт можно переписать без eval
, используя конструкции управления потоком или расширенные условные выражения, чтобы более безопасно обрабатывать логические ветки:
if [ $# -eq 1 ]; then
if [ -f "$1" ]; then
validate < "$1"
else
validate <<< "$1"
fi
else
for param in "$@"; do
validate <<< "$param"
done
fi | pull_data
Здесь мы избегаем использования eval
и манипулируем параметрами напрямую, что делает код более безопасным и менее подверженным уязвимостям.
Заключение
Безопасность — это приоритетная задача при работе со скриптами, особенно при обработке входных данных. Следуя вышеописанным рекомендациям, вы сможете создать более безопасный и надежный скрипт без eval
, сохраняя при этом его читаемость и эффективность.