Всегда ли безопасно использовать `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.