Всегда ли безопасно использовать `eval echo`?


20

Использование evalчасто не рекомендуется, потому что это позволяет выполнять произвольный код. Однако, если мы используем eval echo, то похоже, что остальная часть строки станет аргументом, echoпоэтому она должна быть безопасной. Я прав в этом?


1
не всегда безопасно, вы можете обернуть вилочную бомбу или мерзкий гм -fR *
— μολὼν.λαβέ

Возможно, это всего лишь мысленный эксперимент, но если вы на самом деле думали сделать это, чтобы передать ему несколько аргументов, например -n, вы можете просто сделать это с помощью переменной без кавычек, например, echo $argumentsили если $argumentsэто массив echo "${arguments[@]}". Использование eval echoбессмысленно, даже если это было безопасно.
— JoL

Ответы:


40

контрпример:

DANGEROUS=">foo"
eval echo $DANGEROUS

Произвольные аргументы to echoмогли бы сделать что-то более гнусное, чем создание файла с именем "foo".


6
Также: DANGEROUS="hello;ls"для произвольных команд вместо ls.
— Кусалананда

2
Также: DANGEROUS='$(ls)'(может потребоваться больше экранирования).
— wizzwizz4

Будет eval echo '"'"$DANGEROUS"'"'работать? Похоже на goo.gl/L2pPQP
— Исмаэль Мигель

@IsmaelMiguel Это не работает для примеров wizzwizz, Cyker или sorontar или для чего-либо с двойными кавычками в строке (например DANGEROUS='">foo"').
— Гордон Дэвиссон

Штопать. Хотя я нашел кое-что, что немного помогло
— Исмаэль Мигель

26

@Celada предоставила отличный ответ. Чтобы продемонстрировать evalдействительно зло, вот нечто более гнусное, чем создание файла с именем "foo" :

DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"

И, конечно, может быть что-то более гнусное, чем нечто более гнусное, чем создание файла с именем «foo» .


8
+1 за демонстрацию того, что цитирование переменной как, "$THIS"а не просто как $THIS, даже не помогает!
— Селада

Отправка дополнительной пары цитат, кажется, помогает. Нечто подобное eval echo '"'"$DANGEROUS"'"'. Попробуйте это на goo.gl/L2pPQP
— Исмаэль Мигель

На самом деле, ваш пример не так уж и страшен >foo, потому что «создание файла с именем« foo »» не обязательно все, что >fooделает. Единственное реальное отличие вашего примера в том, что он не оставляет пустой файл. Содержание все еще ушло.
— flarn2006

12

Нет, это не всегда безопасно. Eval может выполнить любую команду.

Безопасная команда, подобная этой (дата не выполняется, поскольку она находится в одинарных кавычках):

$ echo '$(date)'
$(date)

Становится опасным, если используется с eval:

$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016

Конечно, датой может быть любая команда.

Один из способов улучшить это - дополнительно процитировать аргументы в eval:

$ eval echo '\$(date)'
$(date)

Но обычно сложно правильно дважды цитировать выражение.

И становится невозможным контролировать правильное цитирование, если выражение может быть установлено внешним злоумышленником, например:

$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!

1

Хотя это правда, что evalвсегда нужно подходить с осторожностью, eval echoконструкция не всегда бессмысленна и может использоваться безопасно. Недавно я нуждался в этом, чтобы оценить несколько расширений фигурных скобок в том порядке, в котором они мне нужны.

bash делает несколько расширений скобок слева направо, так

xargs -I_ cat _/{11..15}/{8..5}.jpg

расширяется до

xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg

но мне нужно было сделать второе расширение скобки первым, давая

xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg

Лучшее, что я мог придумать, чтобы сделать это, было

xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)

Это работает, потому что одинарные кавычки защищают первый набор фигурных скобок от раскрытия во время синтаксического анализа evalкомандной строки, оставляя их для раскрытия посредством подоболочки, вызываемой eval.

Может быть какая-то хитрая схема с использованием вложенных фигурных скобок, которая позволяет этому происходить за один шаг, но если это так, я слишком стар и глуп, чтобы это увидеть. Есть и другие оболочки, bashкоторые позволяют более аккуратные способы достижения такого рода вещей. Но в любом случае такое использование evalбезопасно, поскольку все его аргументы - это фиксированные строки, которые не содержат раскрытия параметров.


Здесь вам не нужно echo и подстановка команд (которая также зависит от $ IFS). Вы могли бы сделатьeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
— Стефан Chazelas

Это тоже работает, но делает процесс subshell порожденным eval, пока процесс xargs не будет завершен; версия eval echo заставляет эту оболочку исчезнуть еще до запуска xargs. Это, вероятно, важно только для тех, кто такой же анальный, как и я, о том, что отображается в представлениях дерева htop и журналах set -x :-)
— flabdablet
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.