Как работает CVE-2014-7169? Разбивка тестового кода

С выпуском bash, который был исправлен для скорлупы

$ bash --version
GNU bash, version 3.2.52(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test

еще один подобный эксплойт все еще работает и был назначен CVE-2014-7169

$ env X='() { (a)=>\' bash -c "echo date"; cat echo
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
Thu Sep 25 12:47:22 EDT 2014

$ ls echo
echo

В поисках разбивки этого также.

2 ответа

Решение

Баг

CVE-2014-7169 - это ошибка в парсере bash. Парсер Bash использует переменную eol_ungetc_lookahead чтобы разблокировать символы через строки. Эта переменная не была правильно сброшена из reset_parser функция, которая вызывается, например, при некоторых синтаксических ошибках. Используя эту ошибку, можно вставить символ в начало следующей строки ввода bash.

Таким образом, тестовый код вызывает синтаксическую ошибку, используя либо (a)= или же function a a, добавляет символ перенаправления для добавления к следующей строке > и добавляет продолжение строки \, что приводит к любой версии тестового кода:

() { (a)=>\
() { function a a>\

Когда bash выполняется, он обрабатывает переменные из среды, находит эту переменную X является экспортированной функцией и оценивает ее для импорта функции. Но оценка завершается с ошибкой разбора, оставляя > персонаж в eol_ungetc_lookahead переменная. Затем при разборе аргумента команды echo date предвосхищает > характер, ведущий к >echo date, который работает date перенаправлен в файл с именем echo,

Его отношение к предыдущей ошибке

Вышеупомянутая ошибка, очевидно, сильно отличается от первоначальной ошибки в снаряде. На самом деле есть несколько проблем:

  • Bash полностью вычисляет переменную, которая выглядит как экспортируемая функция (начинается с четырех символов () {). CVE-2014-6271.
  • При некоторых условиях возможно вставить символ в переменную ungetc, которая будет добавлена ​​перед следующей строкой ввода. CVE-2014-7169.
  • Bash позволяет обрабатывать каждую переменную среды как экспортированную функцию, если она начинается с четырех символов () {, CVE-2014-6271, CVE-2014-7169, все остальные CVE, где ошибка запускается в парсере bash.
  • Существует ограниченный стек для перенаправления here-doc, и нет проверки на переполнение. CVE-2014-7186, что приводит к повреждению памяти и, вероятно, может использоваться для выполнения произвольного кода.
  • Существует ограниченный стек для вложенных структур управления (select / for / while), с проверками на переполнение. Этот стек все еще поврежден. CVE-2014-7187.

Исправления

  • Первый патч ограничивает bash оценкой одного определения функции в каждой переменной, которая выглядит как экспортируемая функция.
  • Второй патч корректно сбрасывается eol_ungetc_lookahead на reset_parser,
  • Третий патч изменяет способ экспорта функций: теперь они экспортируются в переменные с именем BASH_FUNC_functionname%%,

Поверхность атаки

Большая проблема здесь заключалась в том, что каждая переменная среды может использоваться в качестве вектора для атаки. Как правило, злоумышленники не могут контролировать произвольные переменные среды, в противном случае уже есть другие известные атаки (подумайте о LD_PRELOAD, PATH, IFS...)

sudo не подвержен влиянию, поскольку он удаляет экспортированные функции bash из среды, как упомянуто Gilles на security.SE.

ssh подвергается воздействию. Типичные установки sshd позволяют экспортировать только ограниченный набор переменных среды, как указано в AcceptEnv в sshd_config Например: LANG а также LC_*, Даже при таком агрессивном подходе к созданию белого списка любая переменная может быть вектором атаки.

Мало того, что каждая переменная среды была потенциальным вектором атаки, они выставляли парсер>6000 строк.

Переученные уроки

system, popen и другие потенциально опасны. Вы должны заботиться не только об их аргументах: даже когда аргументы фиксированы во время компиляции, среда является потенциальным вектором атаки. использование fork()/execve() предпочтительно с чистой окружающей средой (но, по крайней мере, ограничьте среду переменными из белого списка, желательно с проверкой их значений). Помните, что система хорошего качества делает то, что должна, а защищенная система делает то, что должна, и ничего более. Вызов полноценной оболочки делает более трудным занятие ничем более сложным.

Сложность - враг безопасности. В эти дни вы можете легко найти людей, рекомендующих более простые оболочки. Большинство оболочек не имеют шокового удара, так как не поддерживают экспортируемые функции. С другой стороны, Bash получил много функций безопасности за эти годы (вы должны вызывать его с -p чтобы избежать потери привилегий при запуске, это дезинфицирует IFS, ...), так что не думайте, что я выступаю за переключение оболочек, это скорее общий совет.

Некоторые выдержки из древней главы Дэвида Уилера "Безопасное программирование для Linux и UNIX HOWTO", посвященной переменным среды, все еще заслуживают перечитывания.

§5.2.3 №1:

Для защищенных программ setuid/setgid следует тщательно извлечь краткий список переменных среды, необходимых для ввода (если они есть). Затем следует стереть всю среду, а затем сбросить небольшой набор необходимых переменных среды до безопасных значений. Там действительно нет лучшего способа, если вы делаете какие-либо звонки в подчиненные программы; не существует практического метода перечисления "всех опасных значений".

§5.2.3 №6:

Если вам действительно нужны пользовательские значения, сначала проверьте значения (чтобы убедиться, что значения соответствуют шаблону для допустимых значений и что они находятся в пределах некоторой разумной максимальной длины).

Сильно размахивая руками, я подозреваю, что новый эксплойт делает следующее:

  1. Обратная косая черта помогает обойти исходный патч, так что строка все еще оценивается.
  2. > сочетается с echo в качестве перенаправления вывода для bash ракушка
  3. С echo расходуется на оценку для определения функции, единственная часть -c аргумент, оставленный для выполнения, dateчей вывод идет к имени файла echo вместо стандартного вывода.

Это лучшее, что я могу придумать, если не читать bash источник, но я подозреваю, что обратная косая черта способствует некоторому переполнению буфера, что позволяет строке среды и аргументу -c быть объединенным.

Другие вопросы по тегам