Кратко
- CGI мог превратить удалённый HTTP-заголовок в переменную окружения Unix; уязвимый Bash распознавал там функцию и мог выполнить текст после конца её определения.
- Удалённая доступность зависела от всей цепочки: внешние данные должны были попасть в окружение до прямого или косвенного запуска Bash.
- Первая заплата оказалась неполной; для окончательного закрытия потребовались последующие пакеты, сокращение наследования окружения, отказ от лишних shell-переходов и доказанный перезапуск живых процессов.
HTTP-заголовок описывает запрос. Переменная окружения описывает контекст процесса. Определение функции является кодом. Shellshock соединил эти три смысла так, что описание незаметно получило возможность действовать.
Первый переход был частью спецификации. RFC 3875 позволяет CGI представлять поля HTTP-заголовков как метавеременные с префиксом HTTP_. В Unix они передаются сценарию как одноимённые переменные окружения. Этот механизм переносил данные и сам по себе не выполнял команд.
Второй переход создавал Bash. Для экспорта функции в другую копию Bash старый механизм помещал её определение в окружение. Уязвимые версии при запуске узнавали такую форму, но не всегда останавливали разбор на конце функции. Добавленный следом текст мог стать командой.
Реальная цепочка выглядела так: удалённый заголовок, метавеременная CGI, наследуемое окружение, запуск Bash, импорт функции, исполнение. Без любого звена этот удалённый путь закрывался. Поэтому перечень машин с Bash не был перечнем доступных целей. CERT/CC и Red Hat приводили в пример CGI, некоторые конфигурации SSH с ограниченными командами и отдельные процессы DHCP-клиентов.
CVE-2014-6271 стал публичным 24 сентября 2014 года. На следующий день CERT/CC выпустил заметку и сообщил об активной эксплуатации. 26 сентября Red Hat признала первый вариант исправления неполным; оставшееся поведение получило CVE-2014-7169, а близкие ошибки разбора — другие идентификаторы. В эти дни слово «обновлено» без точной версии пакета и результата проверки пути мало что доказывало.
Более сильное исправление сузило сам контракт импорта. Обновлённые пакеты вынесли экспортируемые функции в узнаваемое пространство имён вроде BASH_FUNC_name(). Это создавало издержки совместимости, зато лучше отделяло обычные данные окружения от исполняемого определения. Менялась граница полномочий, а не только блокировалась известная строка.
Новый файл на диске ещё не обновлял живое состояние. Red Hat рекомендовала перезапустить службы, использовавшие экспорт функций; пользователям мог потребоваться новый вход, а сессии screen и tmux могли сохранять старые определения. Реестр пакетов не отвечал на вопрос, какой исполняемый файл вызовет долгоживущий процесс.
Практическое реагирование начиналось со схемы вызовов. Какая публичная служба формирует окружение? Какой помощник запускает Bash? От какой учётной записи? Какой родительский процесс живёт ещё со времени до обновления? Пока пакет распространялся, локальный владелец должен был иметь ограниченное право выключить CGI-обработчик, очистить окружение на границе доверия или заменить shell-обёртку прямым запуском.
Shellshock не доказывает, что переменные окружения плохи сами по себе. Он доказывает, что название «метаданные» не ограничивает смысл, который даст им следующий получатель. Момент, когда данные приобретают новый глагол, должен быть явным.
Источники
Обзор для участников
Подробный контекст профиля
Войдите с подходящим уровнем подписки, чтобы открыть полный обзор и примечания к источникам.
Только для Стратегического сообщества
Стратегическое сообщество
Открыто всем читателям. Вступите и войдите, чтобы открыть обзоры профилей.
Вступить в Стратегическое сообществоТолько для Альянса лидеров
Альянс лидеров
Для проверенных владельцев IP-активов и руководителей. Войдите, чтобы открыть обзоры Альянса.
Вступить в Альянс лидеров