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

Одна из ловушек при использовании Терминатора (или любой из оболочек VTE) заключается в том, что параметр -e интерпретируется неверно. несовместимо с xterm и rxvt, если у вас есть более одного токена / слова в команде для выполнения. VTE-оболочки ожидают только один токен, в то время как xterm и rxvt используют все токены после -e . В зависимости от команды Терминатор действительно не сработает.

Дополнительная литература:

20
26.12.2016, 04:05
4 ответа

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

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

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

26
27.01.2020, 19:43

Нет, не всегда безопасно. 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!
12
27.01.2020, 19:43

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

DANGEROUS=">foo"
eval echo $DANGEROUS

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

40
27.01.2020, 19:43

Хотя это правда, что к 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безопасно, поскольку все его аргументы представляют собой фиксированные строки, не содержащие расширений параметров.

1
27.01.2020, 19:43

Теги

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