Вот команда, которую я использовал, чтобы проверить мою оболочку bash на наличие ошибки Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Может кто-нибудь объяснить, пожалуйста, команду в деталях?
bash
shellshock
heemayl
источник
источник
Ответы:
Этот ответ является производным от оригинальной статьи о журнале Fedora Мэтью Миллера, лицензированной по лицензии Creative Commons Attribution-Share Alike 4.0 .
Позволь мне объяснить:
Это выведет «OOPS» на уязвимую систему, но выйдет молча, если bash был исправлен.
Это напечатает «OOPS» в уязвимой системе, но напечатает,
“this is a test”
если bash был исправлен.И вы, наверное, слышали, что это как-то связано с переменными среды. Но почему выполняется код в переменных среды? Ну, это не должно быть - но из-за функции, которую я склонен назвать слишком умной для своего блага, есть место для изъяна. Bash - это то, что вы видите как терминальное приглашение, но это также язык сценариев и возможность определять функции. Вы делаете это так:
и тогда у вас есть новая команда. Имейте в виду, что
echo
здесь на самом деле еще не работает; он просто сохраняется как то, что произойдет, когда мы запустим нашу новую команду. Это будет важно через минуту!Полезно! Но, скажем, по какой-то причине нам нужно выполнить новый экземпляр bash в качестве подпроцесса, и мы хотим запустить мою потрясающую новую команду под этим. Оператор
bash -c somecommand
делает именно это: запускает данную команду в новой оболочке:Ooh. Печальный. Ребенок не унаследовал определение функции. Но это присуще среде - совокупности пар ключ-значение, которые были экспортированы из оболочки. (Это совершенно другая концепция; если вы не знакомы с этим, поверьте мне.) И, оказывается, bash также может экспортировать функции. Так:
Что все хорошо, за исключением того, что механизм, с помощью которого это достигается, является своего рода хитрым . По сути, поскольку нет волшебства Linux / Unix для выполнения функций в переменных среды, функция экспорта фактически просто создает обычную переменную среды, содержащую определение функции. Затем, когда вторая оболочка читает «входящую» среду и встречает переменную с содержимым, похожим на функцию, она оценивает ее.
Теоретически, это совершенно безопасно , потому что, помните, определение функции фактически не выполняет ее . За исключением - и вот почему мы здесь - в коде была ошибка, из-за которой оценка не остановилась, когда был достигнут конец определения функции. Это просто держит движение.
Этого никогда не произойдет, если функция, хранящаяся в переменной окружения, будет создана законным путем
export -f
. Но зачем быть законным? Злоумышленник может просто создать любую старую переменную среды, и если она будет выглядеть как функция, новые оболочки bash подумают, что это так!Итак, в нашем первом примере:
Команда
env
запускает команду с заданным набором переменных. В этом случае мы устанавливаемx
что-то похожее на функцию. Функция - это всего лишь одна:
, на самом деле это простая команда, которая определена как ничего не делающая. Но затем, послеsemi-colon
которого указывается конец определения функции, естьecho
команда. Это не должно быть там, но ничто не мешает нам сделать это.Затем команда для запуска в этой новой среде представляет собой новую оболочку bash, опять же с командой «
echo this is a test
» или «ничего не делать:
», после которой она завершается совершенно безвредно.Но - ой! Когда эта новая оболочка запускается и читает среду, она попадает в
x
переменную и, поскольку она выглядит как функция, она оценивает ее. Определение функции безвредно загружается, а затем запускается и наша вредоносная полезная нагрузка. Таким образом, если вы запустите вышеперечисленное на уязвимой системе, вы получите“OOPS”
печать обратно на себя. Или злоумышленник может сделать намного хуже, чем просто напечатать вещи.источник
env
это не обязательно. Вы можете получить тот же результат (прошел / не прошел в зависимости от того, был ли обновлен Bash) с помощью команды без него:x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Это связано с тем, что предшествующая команде с присвоением переменной передает эту переменную и ее значение в командную (bash -c "..."
в данном случае) среду.env
, определяется оболочкой, из которой запускается тест, а не тестируемой оболочкой. (Они могут быть одинаковыми. Даже тогда мы тестируем, как bash обрабатывает свою собственную среду.) Оболочки в стиле Борна принимаютNAME=value command
синтаксис; Оболочки в стиле C (напримерcsh
,tcsh
) не делают. Таким образом, тест является немного более переносимымenv
(за счет порождения путаницы в том, как он работает).В не исправленной версии
bash
он сохраняет экспортированные определения функций в качестве переменных среды.Сохранить функцию
x
как,И проверьте его определение как,
Таким образом, можно использовать это, определяя свои собственные переменные среды и интерпретируя их как определения функций. Например
env x='() { :;}'
, будет рассматриваться какЧто делает команда для проверки снарядов,
От
man env
,env
- запустить программу в измененной среде.:
ничего не делать, кроме выходов со статусом выхода0
. увидеть большеКогда новый экземпляр неотправленного bash запускается как
bash -c "echo this is a test"
, созданная переменная окружения обрабатывается как функция и загружается. Соответственно получается выходисточник
env test='() { echo "anything"; }' bash -c "echo otherthing"
вы увидите на выходеotherthing
. Это исправлено в патче. не стесняйтесь, если мне все еще не ясно.unpatched bash
функции можно вызывать функцию, как она определена, а в исправленииbash
само определение отсутствует.echo vulnerable
), не выполняется. Обратите внимание, что в последних исправлениях переданная функция должна иметь определенный префикс (env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). Некоторые более поздние патчи могут использовать%%
вместо первого()
.