Вот команда, которую я использовал, чтобы проверить мою оболочку bash на наличие ошибки Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Может кто-нибудь объяснить, пожалуйста, команду в деталях?
Вот команда, которую я использовал, чтобы проверить мою оболочку bash на наличие ошибки Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Может кто-нибудь объяснить, пожалуйста, команду в деталях?
Ответы:
Этот ответ является производным от оригинальной статьи о журнале 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”
печать обратно на себя. Или злоумышленник может сделать намного хуже, чем просто напечатать вещи.
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
как,
$ 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
,
env
- запустить программу в измененной среде.
:
ничего не делать, кроме выходов со статусом выхода 0
. увидеть больше
Когда новый экземпляр неотправленного bash запускается как bash -c "echo this is a test"
, созданная переменная окружения обрабатывается как функция и загружается. Соответственно получается выход
уязвимый это проверка
Примечание: эхо за пределами определения функции было неожиданно выполнено во время запуска bash. Определение функции - это всего лишь шаг к выполнению оценки и эксплуатации, само определение функции и используемая переменная окружения являются произвольными. Оболочка просматривает переменные окружения, видит x, который выглядит так, как будто он соответствует ограничениям, которые он знает о том, как выглядит определение функции, и он оценивает строку, непреднамеренно выполняя также эхо (которое может быть любой командой, злонамеренной или нет) , Также смотрите это
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"
). Некоторые более поздние патчи могут использовать %%
вместо первого ()
.