bash сохраняет экспортированные определения функций как переменные среды. Экспортированные функции выглядят следующим образом:
$ foo() { bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { bar
}
То есть переменная среды foo
имеет буквальное содержание:
() { bar
}
Когда запускается новый экземпляр bash, он ищет эти специально созданные переменные среды и интерпретирует их как определения функций. Вы даже можете написать его самостоятельно и убедиться, что он по-прежнему работает:
$ export foo='() { echo "Inside function"; }'
$ bash -c 'foo'
Inside function
К сожалению, синтаксический анализ определений функций из строк (переменных среды) может иметь более широкий эффект, чем предполагалось. В версиях без исправлений он также интерпретирует произвольные команды, которые появляются после завершения определения функции. Это связано с недостаточными ограничениями при определении приемлемых функционально-подобных строк в среде. Например:
$ export foo='() { echo "Inside function" ; }; echo "Executed echo"'
$ bash -c 'foo'
Executed echo
Inside function
Обратите внимание, что эхо вне определения функции было неожиданно выполнено во время запуска bash. Определение функции - это всего лишь шаг к тому, чтобы выполнить оценку и выполнить эксплойт, само определение функции и используемая переменная среды являются произвольными. Оболочка смотрит на переменные среды, видит foo
, который выглядит так, как будто он соответствует ограничениям, которые он знает о том, как выглядит определение функции, и оценивает строку, непреднамеренно также выполняя эхо (которое может быть любым команда, злонамеренная или нет).
Это считается небезопасным, потому что переменные обычно не допускаются или не ожидаются сами по себе, чтобы напрямую вызывать произвольный код, содержащийся в них. Возможно, ваша программа устанавливает переменные среды из ненадежного пользовательского ввода. Было бы весьма неожиданно, если бы этими переменными среды можно было манипулировать таким образом, чтобы пользователь мог запускать произвольные команды без вашего явного намерения сделать это, используя эту переменную среды по такой причине, объявленной в коде.
Вот пример жизнеспособной атаки. Вы запускаете веб-сервер, который запускает уязвимую оболочку где-то в рамках своего жизненного цикла. Этот веб-сервер передает переменные среды в сценарий bash, например, если вы используете CGI, информация о HTTP-запросе часто включается в качестве переменных среды с веб-сервера. Например, HTTP_USER_AGENT
может быть установлен для содержимого вашего пользовательского агента. Это означает, что если вы подмените свой пользовательский агент чем-то вроде '() {:; }; echo foo ', при запуске этого сценария оболочки будет выполнено echo foo
. Опять же, echo foo
может быть чем угодно, вредоносным или нет.
Вам нужно будет вызвать следующую команду, которая вернет данные учетной записи пользователя. Для этого вам не обязательно быть root ( / etc / passwd
имеет разрешения -rw-r - r -
по умолчанию), но вам все равно нужно использовать cli как действующий пользователь.
grep
или
id
или вы можете проверить, есть ли в папке с вашим именем пользователя существует в / home
каталоге