Объяснение команды для проверки снарядов

Вот команда, которую я использовал, чтобы проверить мою оболочку bash на наличие ошибки Shellshock:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Может кто-нибудь, пожалуйста, объясните команду в деталях?

2 ответа

Решение

Этот ответ является производным от оригинальной статьи о журнале Fedora Мэтью Миллера, лицензированной по лицензии Creative Commons Attribution-Share Alike 4.0.

Позволь мне объяснить:

env x='() { :;}; echo OOPS' bash -c :

Это выведет "OOPS" на уязвимую систему, но выйдет молча, если bash был исправлен.

env x='() { :;}; echo OOPS' bash -c "echo this is a test"

Это напечатает "OOPS" в уязвимой системе, но напечатает “this is a test” если bash был исправлен

И вы, наверное, слышали, что это как-то связано с переменными среды. Но почему выполняется код в переменных среды? Ну, это не должно быть - но из-за функции, которую я склонен назвать слишком умной для своего блага, есть место для изъяна. Bash - это то, что вы видите как терминальное приглашение, но это также язык сценариев и возможность определять функции. Вы делаете это так:

$ Ubuntu()  { echo "Ubuntu is awesome."; }

и тогда у вас есть новая команда. Имейте в виду, что echo здесь на самом деле еще не бежать; он просто сохраняется как то, что произойдет, когда мы запустим нашу новую команду. Это будет важно через минуту!

$ Ubuntu
 Ubuntu is awesome.

Полезно! Но, скажем, по какой-то причине нам нужно выполнить новый экземпляр bash в качестве подпроцесса, и мы хотим запустить мою потрясающую новую команду под этим. Заявление bash -c somecommand делает именно это: запускает данную команду в новой оболочке:

$ bash -c Ubuntu
  bash: Ubuntu: command not found

Ooh. Печальный. Ребенок не унаследовал определение функции. Но это присуще среде - совокупности пар ключ-значение, которые были экспортированы из оболочки. (Это совершенно другая концепция; если вы не знакомы с этим, поверьте мне.) И, оказывается, bash также может экспортировать функции. Так:

$ export -f Ubuntu
$ bash -c Ubuntu
  Ubuntu is awesome.

Что все хорошо, за исключением того, что механизм, с помощью которого это достигается, является своего рода хитрым. По сути, поскольку нет волшебства Linux/Unix для выполнения функций в переменных среды, функция экспорта фактически просто создает обычную переменную среды, содержащую определение функции. Затем, когда вторая оболочка читает "входящую" среду и встречает переменную с содержимым, похожим на функцию, она оценивает ее.

Теоретически, это совершенно безопасно, потому что, помните, определение функции фактически не выполняет ее. За исключением - и вот почему мы здесь - в коде была ошибка, из-за которой оценка не остановилась, когда был достигнут конец определения функции. Это просто держит движение.

Этого никогда не произойдет, если функция, хранящаяся в переменной окружения, будет создана законным образом, с export -f, Но зачем быть законным? Злоумышленник может просто создать любую старую переменную среды, и если она будет выглядеть как функция, новые оболочки bash подумают, что это так!

Итак, в нашем первом примере:

env x='() { :;}; echo OOPS' bash -c "echo this is a test"

env Команда запускает команду с заданным набором переменных. В этом случае мы устанавливаем x к чему-то, что выглядит как функция. Функция только одна :, которая на самом деле простая команда, которая определяется как ничего не делать. Но потом, после semi-colon который сигнализирует об окончании определения функции, есть echo команда. Это не должно быть там, но ничто не мешает нам сделать это.

Затем команда для запуска в этой новой среде представляет собой новую оболочку bash, снова сecho this is a test"Или" ничего не делать :Команда, после которой она выйдет, совершенно безобидна.

Но - ой! Когда эта новая оболочка запускается и читает среду, она попадает в x переменная, и так как она выглядит как функция, она оценивает ее. Определение функции безвредно загружается, а затем запускается и наша вредоносная полезная нагрузка. Таким образом, если вы запустите вышеуказанное на уязвимой системе, вы получите “OOPS” напечатан обратно на вас. Или злоумышленник может сделать намного хуже, чем просто напечатать вещи.

В неотправленной версииbash он сохраняет экспортированные определения функций как переменные среды.

Сохранить функцию x как,

$ x() { bar; }
$ export -f x

И проверьте его определение как,

$ env | grep -A1 x
x=() {  bar
}

Таким образом, можно использовать это, определяя свои собственные переменные среды и интерпретируя их как определения функций. Например env x='() { :;}' будет рассматриваться как

x() { :;
}

Что делает команда для проверки снарядов,

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

От man env,

  1. env - запустить программу в измененной среде.

  2. : ничего не делать, кроме выхода со статусом выхода 0, увидеть больше

  3. Когда новый экземпляр непатентованного bash запущен как bash -c "echo this is a test"созданная переменная среды обрабатывается как функция и загружается. Соответственно получается выход

    уязвимый
    Это тест

Примечание: эхо за пределами определения функции было неожиданно выполнено во время запуска bash. Определение функции - это всего лишь шаг к выполнению оценки и эксплуатации, само определение функции и используемая переменная окружения являются произвольными. Оболочка просматривает переменные окружения, видит x, который выглядит так, как будто он соответствует ограничениям, которые он знает о том, как выглядит определение функции, и он оценивает строку, непреднамеренно выполняя также эхо (которое может быть любой командой, злонамеренной или нет), Также смотрите это

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