Дезинфекция пользовательского ввода в bash в целях безопасности

Как очистить пользовательский ввод в сценарии bash, чтобы затем передать его в качестве аргумента другой программе оболочки? Я хочу предотвратить следующее:

INPUT="filename;rm -rf /"
ls $INPUT

Я думал, что этого должно быть достаточно, чтобы заключить пользовательский ввод в двойные кавычки, например:

ls "$INPUT"

но что, если в $INPUT есть двойная кавычка?

Или bash уже занимается этой проблемой?


person johnf    schedule 25.11.2010    source источник


Ответы (1)


Короткая

Bash уже имеет дело с этим. Достаточно процитировать.

ls "$INPUT"

Долго

Примерное руководство по тому, как оболочка анализирует эту строку:

"ls \"$INPUT\""                     # Raw command line.
["ls", "\"$INPUT\""]                # Break into words.
["ls", "\"filename; rm -rf /\""]    # Perform variable expansion.
["ls", "\"filename; rm -rf /\""]    # Perform word splitting (no change).
["ls", "filename; rm -rf /"]        # Remove quotes.

Из-за кавычек переменная $INPUT не подвергается разбиению на слова. ls будет искать файл с именем filename; rm -rf /.

Если бы вы не указали его, расширение происходило бы по-другому:

"ls $INPUT"                             # Raw command line.
["ls", "$INPUT"]                        # Break into words.
["ls", "filename; rm -rf /"]            # Perform variable expansion.
["ls", "filename;", "rm", "-rf", "/"]   # Perform word splitting.

По крайней мере, вы можете утешаться тем, что на самом деле это не приведет к выполнению rm -rf /. Вместо этого он передаст каждую из этих строк как имя файла в ls. Вы ls удалите некоторые файлы, которые не планировали, но, по крайней мере, это не вызовет случайного выполнения нежелательных команд.

jkugelman$ VAR='.; echo hi'
jkugelman$ ls $VAR
ls: .;: No such file or directory
ls: echo: No such file or directory
ls: hi: No such file or directory

Выдержки из "человека баш":

ЦИТАТА

Цитирование используется для удаления специального значения определенных символов или слов из оболочки. Кавычки можно использовать для отключения специальной обработки специальных символов, предотвращения распознавания зарезервированных слов как таковых и предотвращения расширения параметров.

РАСШИРЕНИЕ

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

Только раскрытие фигурных скобок, разбиение на слова и расширение имени пути могут изменить количество слов расширения; другие расширения расширяют одно слово до одного слова. Единственным исключением являются расширения "$@" и "${name[@]}", как описано выше (см. ПАРАМЕТРЫ).

Разделение слов

Оболочка сканирует результаты раскрытия параметров, подстановки команд и арифметического расширения, которые не происходили в двойных кавычках, для разделения слов.

Удаление цитаты

После предыдущих расширений все вхождения символов \, ' и " без кавычек, которые не являются результатом одного из приведенных выше расширений, удаляются.

person John Kugelman    schedule 25.11.2010
comment
Хороший звонок, с одной оговоркой, что это не относится к eval - person SiegeX; 25.11.2010
comment
Обратите внимание, что bash до 4.0 выполнял подстановку (но не разбиение) при расширении тильды, и не было никакого способа избежать этого, кроме как с помощью временной переменной (или вообще отключить подстановку с помощью set -f). - person Stephane Chazelas; 06.02.2014
comment
Также обратите внимание, что вообще говоря, вы должны сделать ls -- "$INPUT" или ls -d -- "$INPUT", если вы не собираетесь перечислять содержимое каталогов. - person Stephane Chazelas; 06.02.2014
comment
Знаю, старая запись, но eval дело важное. Команда rm будет выполнена, если они сделают eval ls $INPUT. Если используется eval, то обратная кавычка и подвыражения $(cmd) также являются возможными угрозами. - person rich p; 26.01.2016