Побег из песочницы Chrome при помощи RIDL
Уязвимости, дающие утечку кросс-процессной памяти, могут быть использованы для выхода из песочницы Chrome. Злоумышленнику по-прежнему необходимо скомпрометировать визуализацию до начала этой атаки. Для защиты от атак на уязвимые процессоры убедитесь, что ваш микрокод обновлен, и отключите гиперпоточность (HT).
В этой статье мы рассмотрим изолированную программную среду и, в частности, влияние
Вот упрощенный обзор того, как выглядит модель процесса Chrome:
Процессы рендеринга находятся в отдельных песочницах, и доступ к ядру ограничен, например, с помощью фильтра seccomp в Linux или
Механизм по умолчанию для межпроцессного взаимодействия в Chrome называется Mojo. Под капотом он поддерживает каналы сообщений/данных и разделяемую память, но вы обычно используете одну из языковых привязок более высокого уровня в C++, Java или JavaScript. То есть вы создаете интерфейс с методами на пользовательском языке определения интерфейса (IDL), Mojo создает для вас заглушки на выбранном вами языке, и вы просто реализуете эту функциональность. Чтобы увидеть, как это выглядит на практике, вы можете проверить URLLoaderFactory в
Одна примечательная особенность заключается в том, что Mojo позволяет вам пересылать конечные точки IPC по существующему каналу. Это широко используется в кодовой базе Chrome, т. е. всякий раз, когда вы видите параметр pending_receiver или pending_remote в файле .mojom.
Под капотом Mojo использует канал сообщений для конкретной платформы между процессами или, более конкретно, между узлами в Mojo. Два узла могут быть связаны напрямую друг с другом, но это не обязательно, так как Mojo поддерживает маршрутизацию сообщений. Один узел в сети называется брокерским узлом, который имеет некоторые дополнительные обязанности по настройке каналов узла и выполнению некоторых действий, ограниченных песочницей.
Сами оконечные точки IPC называются портами . В приведенном выше примере URLLoaderFactory и клиент, и сторона реализации идентифицируются портом. В коде, порт выглядит как
Указанные выше peer_node_name и peer_port_name являются 128-битными случайными целыми числами, используемыми для адресации. Если вы отправляете сообщение в порт, он сначала перенаправляет его на нужный узел, а принимающий узел ищет имя порта на карте локальных портов и помещает сообщение в нужную очередь сообщений.
Конечно, это означает, что если у вас есть уязвимость утечки информации в процессе браузера, вы можете слить имена портов и использовать их для внедрения сообщений в привилегированные каналы IPC. И на самом деле, на это ссылаютса в разделе
«[...] любой узел может отправлять любое сообщение на любой порт любого другого узла, если он знает имена портов и узлов. [...] Поэтому важно не просачивать имена портов в узлы, которым не должна быть предоставлена соответствующая возможность ».
Хорошим примером ошибки, которая может быть легко использована для утечки номеров портов, был
RIDL
Чтобы использовать это сценарий с аппаратной уязвимостью, я искал ошибку, которая позволяет утечке памяти через границу процесса. RIDL от
Были выпущены обновления микрокода и ОС для защиты от атак MDS. Тем не менее, если вы прочтете
Вы можете найти multiple PoCs for
Я закончил тем, что написал два эксплойта для Chrome, используя разные варианты MDS, один из которых предназначен для сборки Linux на Xeon Gold 6154, а другой для Windows на Core i7-7600U. Я опишу оба, так как они в итоге ставили разные задачи при применении их на практике.
Микроархитектурная выборка данных Fill Buffer (MFBDS)
Моим первым эксплойтом было использование MFBDS, который предназначается для буфера заполнения строки ЦП. PoC очень прост:
После этого вы получите временный доступ к массиву зондов, чтобы увидеть, какой индекс был кэширован.
Вы можете изменить 0 в начале, чтобы контролировать смещение в строке кэша для вашей утечки. Кроме того, вы захотите реализовать префиксный или суффиксный фильтр для пропущенного значения, как описано в
Для моей первой цели утечки я выбрал привилегированную
/etc/passwd на
Следующим шагом будет запуск повторного доступа к имени порта привилегированного загрузчика. Заставить процесс браузера делать сетевые запросы может быть одним из вариантов, но, похоже, слишком много ресурсов затрачиваетса. Вместо этого я решил настроить поиск портов в узле.
Каждый узел имеет хеш-карту, в которой хранятся все
Карта начинается с размера сегмента примерно 700 на свежем экземпляре Chrome и растет в основном с количеством визуализаторов. Это делает атаку неосуществимой, поскольку нам придется грубо форсировать как индекс сегмента, так и смещение строки кэша (1 в 4 благодаря выравниванию). Однако я заметил путь к коду, который позволяет вам создавать большое количество привилегированных URLLoaderFactories с помощью сервисных работников. Если вы создадите сервисного воркера с включенной
Единственное, чего не хватает, - это удалить целевое значение из кэша L1. Кажется, простое заполнение наших сообщений 32 КБ данных на практике помогает, так как я предполагаю, что данные будут загружены в кэш L1 жертвы и изгнать все остальное.
Подводя итог всему эксплойту:
В ноябре 2019 года были выпущены новые варианты MDS-атак, и, поскольку TAA PoC оказался быстрее, чем мой эксплойт MFBDS, я решил адаптировать его к эксплойту Chrome. Кроме того, VUSec выпустил эксплойт, предназначенный для операций хранилища, который должен позволить нам избавиться от требования очистки кеша, если мы сможем получить секрет для записи по разным адресам в памяти. Это должно произойти, если мы можем запустить браузер для отправки сообщения на привилегированный порт. В этом сценарии к имени секретного порта также будет добавляться имя узла, и мы можем использовать методы из бумаги RIDL для легкой фильтрации по нему.
Я также начал искать лучший примитив и обнаружил, что если я смогу пообщатса с
Чтобы выяснить, как инициировать сообщения из процесса браузера в NetworkService, я посмотрел на методы IPC в интерфейсе, чтобы найти способ, который выглядит так, как будто я могу влиять на него из средства визуализации.
Как только мы сливаем имя порта из скомпрометированного средства визуализации, мы получим примитив для написания базы данных sqlite3 с полностью контролируемым путем.
Хотя поначалу это звучало не очень полезно, на самом деле вы можете использовать его, чтобы добиться выполнения кода. Я заметил, что пакетные файлы Windows - очень простительный формат файлов. Если у вас есть мусор в начале файла, он пропустит его до следующего «\ r \ n» и выполнит оттуда следующую команду. В своем эксплойте я использую его для создания файла cookies.bat в каталоге автозапуска пользователя, добавления cookie с «\ r \ n» и командой в нем, и он будет выполнен при следующем входе в систему.
В конце концов, этот эксплойт работал в среднем за 1-2 минуты и последовательно работал менее чем за 5 минут на моей машине. И я уверен, что это может быть значительно улучшено, так как я видел много ускорений от небольших изменений и различных методов. Например, MLPDS кажется даже быстрее на практике, чем вариант, который я использую.
Резюме эксплойта:
Когда я начал работать над этим, я был удивлен тем, что он все еще может использоваться, хотя уязвимости были публичны некоторое время. Если вы прочтете руководство по этой теме, они, как правило, расскажут о том, как были устранены эти уязвимости, если ваша ОС обновлена, с указанием, что вам следует отключить гиперпоточность, чтобы полностью защитить себя. Сосредоточение внимания на митигации определенно дало мне ложное представление о том, что уязвимости устранены, и я думаю, что в этих статьях можно было бы более четко понять, как оставить включенным гиперпоточность.
При этом я хотел бы, чтобы вы убрали две вещи из этого поста. Во-первых, ошибки утечки информации могут быть не просто обходом ASLR. Даже если бы не зависимость от секретных имен портов, были бы утечки других интересных данных, например UnguessableTokens Chrome, куки Gmail или конфиденциальные данные в других процессах на машине. Если у вас есть идея, как найти утечки информации в масштабе, Chrome может быть хорошей целью.
Во-вторых, я долгое время игнорировал аппаратные уязвимости, поскольку они находятся за пределами моей зоны компетенции. Тем не менее, я надеюсь, что смог дать вам информацию об их влиянии с помощью этого поста, чтобы помочь вам принять решение, стоит ли отключить гиперпоточность. Существует много возможностей для изучения того, какие другие программы могут быть взломаны подобным образом, и я хотел бы видеть больше примеров применения аппаратных ошибок для преодоления границ безопасности программного обеспечения.
Источник:
Уязвимости, дающие утечку кросс-процессной памяти, могут быть использованы для выхода из песочницы Chrome. Злоумышленнику по-прежнему необходимо скомпрометировать визуализацию до начала этой атаки. Для защиты от атак на уязвимые процессоры убедитесь, что ваш микрокод обновлен, и отключите гиперпоточность (HT).
В этой статье мы рассмотрим изолированную программную среду и, в частности, влияние
Ссылка скрыта от гостей
и подобных аппаратных уязвимостей при использовании скомпрометированного средства визуализации. Механизм Chrome IPC Mojo основан на секретах для маршрутизации сообщений, и утечка этих секретов позволяет отправлять сообщения на привилегированные интерфейсы и выполнять действия, которые не должны выполняться средством визуализации. Мы будем использовать это для чтения произвольных локальных файлов, а также для запуска файла .bat вне песочницы в Windows. На момент написания статьи как Apple, так и Microsoft активно работали над исправлением, чтобы предотвратить эту атаку в сотрудничестве с командой безопасности Chrome.Вот упрощенный обзор того, как выглядит модель процесса Chrome:
Процессы рендеринга находятся в отдельных песочницах, и доступ к ядру ограничен, например, с помощью фильтра seccomp в Linux или
Ссылка скрыта от гостей
в Windows. Но для того, чтобы средство рендеринга сделало что-нибудь полезное, ему нужно пообщатса с другими процессами для выполнения различных действий. Например, чтобы загрузить изображение, необходимо попросить сетевой сервис получить его от его имени.Механизм по умолчанию для межпроцессного взаимодействия в Chrome называется Mojo. Под капотом он поддерживает каналы сообщений/данных и разделяемую память, но вы обычно используете одну из языковых привязок более высокого уровня в C++, Java или JavaScript. То есть вы создаете интерфейс с методами на пользовательском языке определения интерфейса (IDL), Mojo создает для вас заглушки на выбранном вами языке, и вы просто реализуете эту функциональность. Чтобы увидеть, как это выглядит на практике, вы можете проверить URLLoaderFactory в
Ссылка скрыта от гостей
,
Ссылка скрыта от гостей
и
Ссылка скрыта от гостей
Ссылка скрыта от гостей
Ссылка скрыта от гостей
.Одна примечательная особенность заключается в том, что Mojo позволяет вам пересылать конечные точки IPC по существующему каналу. Это широко используется в кодовой базе Chrome, т. е. всякий раз, когда вы видите параметр pending_receiver или pending_remote в файле .mojom.
Под капотом Mojo использует канал сообщений для конкретной платформы между процессами или, более конкретно, между узлами в Mojo. Два узла могут быть связаны напрямую друг с другом, но это не обязательно, так как Mojo поддерживает маршрутизацию сообщений. Один узел в сети называется брокерским узлом, который имеет некоторые дополнительные обязанности по настройке каналов узла и выполнению некоторых действий, ограниченных песочницей.
Сами оконечные точки IPC называются портами . В приведенном выше примере URLLoaderFactory и клиент, и сторона реализации идентифицируются портом. В коде, порт выглядит как
Ссылка скрыта от гостей
:
Код:
class Port : public base::RefCountedThreadSafe<Port> {
public:
// [...]
// Текущее состояние порта.
State state;
// Адрес узла и порта, на который следует направлять события ОТ этого порта.
// Обратите внимание, что это НЕ обязательно адрес порта, который в данный момент отправляет
// события в этот порт.
NodeName peer_node_name;
PortName peer_port_name;
// Следующий доступный порядковый номер для использования в исходящих событиях сообщений пользователя
// исходящий из этого порта.
uint64_t next_sequence_num_to_send;
// [...]
}
Указанные выше peer_node_name и peer_port_name являются 128-битными случайными целыми числами, используемыми для адресации. Если вы отправляете сообщение в порт, он сначала перенаправляет его на нужный узел, а принимающий узел ищет имя порта на карте локальных портов и помещает сообщение в нужную очередь сообщений.
Конечно, это означает, что если у вас есть уязвимость утечки информации в процессе браузера, вы можете слить имена портов и использовать их для внедрения сообщений в привилегированные каналы IPC. И на самом деле, на это ссылаютса в разделе
Ссылка скрыта от гостей
основной документации Mojo:«[...] любой узел может отправлять любое сообщение на любой порт любого другого узла, если он знает имена портов и узлов. [...] Поэтому важно не просачивать имена портов в узлы, которым не должна быть предоставлена соответствующая возможность ».
Хорошим примером ошибки, которая может быть легко использована для утечки номеров портов, был
Ссылка скрыта от гостей
от
Ссылка скрыта от гостей
. Это было целочисленное переполнение в реализации
Ссылка скрыта от гостей
которое позволило вам прочитать произвольный объем памяти кучи перед BLOB-объектом в процессе браузера. Тогда эксплойт будет выглядеть примерно так:- Компромитация рендерера.
- Используйте ошибку blob для утечки кучи памяти.
- Поиск в памяти портов (действительное состояние + 16 старших байтов энтропии).
- Используйте пропущенные порты, чтобы внедрить сообщение в привилегированное соединение IPC.
RIDL
Чтобы использовать это сценарий с аппаратной уязвимостью, я искал ошибку, которая позволяет утечке памяти через границу процесса. RIDL от
Ссылка скрыта от гостей
кажется идеальным кандидатом, поскольку обещает именно это: он позволяет вам пропускать данные из различных внутренних буферов на задействованных ЦП. Для получения подробной информации о том, как это работает, посмотрите
Ссылка скрыта от гостей
или
Ссылка скрыта от гостей
поскольку они объясняют это гораздо лучше, чем я.Были выпущены обновления микрокода и ОС для защиты от атак MDS. Тем не менее, если вы прочтете
Ссылка скрыта от гостей
по этой теме, вы заметите, что меры по смягчению очищают затронутые буферы при переходе в менее привилегированный контекст выполнения. Если ваш процессор поддерживает гиперпоточность, вы все равно сможете пропускать данные из второго потока, работающего на вашем физическом ядре. Для решения этой проблемы
Ссылка скрыта от гостей
либо отключить гиперпоточность, либо реализовать планировщик группы.Вы можете найти multiple PoCs for
Ссылка скрыта от гостей
Ссылка скрыта от гостей
Ссылка скрыта от гостей
в Интернете, некоторые из них уже доступны с мая 2019 г. PoC представлены с различными свойствами:- Они ориентированы либо на loads либо на stores .
- Некоторые требуют, чтобы секрет был сброшен из кэша L1.
- Вы можете управлять индексом в строке 64-байтового кэша, чтобы получить утечку из 64-битного значения из предыдущего доступа.
- Скорость сильно варьируется в зависимости от варианта и эксплойта. Самый высокий отчет, который я видел,
Ссылка скрыта от гостейБрэндона Фалька сСсылка скрыта от гостейс 228 КБ / с. Для сравнения, наивный эксплойт на моей машине достигает только 25 КБ / с.
Ссылка скрыта от гостей
описываются некоторые примитивы синхронизации для целевых значений, обычно требуется запускать повторный доступ к секрету, чтобы полностью его утечь.Я закончил тем, что написал два эксплойта для Chrome, используя разные варианты MDS, один из которых предназначен для сборки Linux на Xeon Gold 6154, а другой для Windows на Core i7-7600U. Я опишу оба, так как они в итоге ставили разные задачи при применении их на практике.
Микроархитектурная выборка данных Fill Buffer (MFBDS)
Моим первым эксплойтом было использование MFBDS, который предназначается для буфера заполнения строки ЦП. PoC очень прост:
Код:
xbegin out ; start TSX to catch segfault
mov rax, [0] ; read from page 0 => leaks a value from line fill buffer
; the rest will only execute speculatively
and rax, 0xff ; mask out one byte
shl rax, 0xc ; use as page index
add rax, 0x13370000 ; add address of probe array
prefetchnta [rax] ; access into probe array
xend
out: nop
После этого вы получите временный доступ к массиву зондов, чтобы увидеть, какой индекс был кэширован.
Вы можете изменить 0 в начале, чтобы контролировать смещение в строке кэша для вашей утечки. Кроме того, вы захотите реализовать префиксный или суффиксный фильтр для пропущенного значения, как описано в
Ссылка скрыта от гостей
. Обратите внимание, что это приводит только к утечке значений, которых нет в кеше L1, поэтому вам нужно иметь способ извлечь секрет из кеша между доступами.Для моей первой цели утечки я выбрал привилегированную
Ссылка скрыта от гостей
. Как упомянуто выше, URLLoaderFactory используется средством визуализации для выборки сетевых ресурсов. Он будет применять ту же политику происхождения (фактически на том же сайте) для вашего средства визуализации, чтобы убедиться, что вы не можете нарушить ограничения веб-платформы. Тем не менее, процесс браузера также использует URLLoaderFactories для различных целей, и те имеют дополнительные привилегии. Помимо игнорирования политики одного и того же происхождения, им также разрешено загружать локальные файлы. Таким образом, если мы можем слить одно из имен их портов, мы можем использовать его для загрузки/etc/passwd на
Ссылка скрыта от гостей
.Следующим шагом будет запуск повторного доступа к имени порта привилегированного загрузчика. Заставить процесс браузера делать сетевые запросы может быть одним из вариантов, но, похоже, слишком много ресурсов затрачиваетса. Вместо этого я решил настроить поиск портов в узле.
Код:
class COMPONENT_EXPORT(MOJO_CORE_PORTS) Node {
// [...]
std::unordered_map<LocalPortName, scoped_refptr<Port>> ports_;
// [...]
}
Ссылка скрыта от гостей
. Если мы отправим сообщение на несуществующий порт, целевой узел найдет
Ссылка скрыта от гостей
на карте, увидит, что оно не существует, и отбросит сообщение. Если имя нашего порта окажется в том же сегменте хэша, что и другое имя порта, он будет
Ссылка скрыта от гостей
неизвестного порта, чтобы сравнить его с ним. Это также загрузит само имя порта в кеш, поскольку он обычно хранится в той же строке кеша, что и хеш. MFBDS позволяет нам пропускать всю строку кэша, даже если значение не было получено напрямую.Карта начинается с размера сегмента примерно 700 на свежем экземпляре Chrome и растет в основном с количеством визуализаторов. Это делает атаку неосуществимой, поскольку нам придется грубо форсировать как индекс сегмента, так и смещение строки кэша (1 в 4 благодаря выравниванию). Однако я заметил путь к коду, который позволяет вам создавать большое количество привилегированных URLLoaderFactories с помощью сервисных работников. Если вы создадите сервисного воркера с включенной
Ссылка скрыта от гостей
, каждая навигация верхнего уровня
Ссылка скрыта от гостей
. Просто создав несколько фреймов и остановив запросы на стороне сервера, вы можете одновременно поддерживать несколько тысяч загрузчиков и значительно упростить грубую силу.Единственное, чего не хватает, - это удалить целевое значение из кэша L1. Кажется, простое заполнение наших сообщений 32 КБ данных на практике помогает, так как я предполагаю, что данные будут загружены в кэш L1 жертвы и изгнать все остальное.
Подводя итог всему эксплойту:
- Компрометация рендерера.
- Запустите эксплойт RIDL в процессах $ NUM_CPU-1 с различными смещениями строк кэша.
- Установите сервисный работник с предварительной загрузкой навигации.
- Создавайте множество фреймов и блокируйте их запросы.
- Отправлять сообщения в сетевой процесс со случайными именами портов.
- Если мы столкнемся с индексом сегмента, процесс в 2. может привести к утечке имени порта.
- Поддать сообщение в URLLoaderFactory для загрузки локальных файлов на
Ссылка скрыта от гостей.
В ноябре 2019 года были выпущены новые варианты MDS-атак, и, поскольку TAA PoC оказался быстрее, чем мой эксплойт MFBDS, я решил адаптировать его к эксплойту Chrome. Кроме того, VUSec выпустил эксплойт, предназначенный для операций хранилища, который должен позволить нам избавиться от требования очистки кеша, если мы сможем получить секрет для записи по разным адресам в памяти. Это должно произойти, если мы можем запустить браузер для отправки сообщения на привилегированный порт. В этом сценарии к имени секретного порта также будет добавляться имя узла, и мы можем использовать методы из бумаги RIDL для легкой фильтрации по нему.
Я также начал искать лучший примитив и обнаружил, что если я смогу пообщатса с
Ссылка скрыта от гостей
, это позволит мне создать новый
Ссылка скрыта от гостей
и тем самым выбрать
Ссылка скрыта от гостей
к
Ссылка скрыта от гостей
базы данных sqlite3, в которой хранятся файлы cookie.Чтобы выяснить, как инициировать сообщения из процесса браузера в NetworkService, я посмотрел на методы IPC в интерфейсе, чтобы найти способ, который выглядит так, как будто я могу влиять на него из средства визуализации.
Ссылка скрыта от гостей
попался на глаза, и на самом деле этот метод вызывается каждый раз, когда обновляется соединение WebRTC. Вам просто нужно создать поддельное соединение WebRTC, и каждый раз, когда вы помечаете его как подключенное / отключенное, оно вызывает новое сообщение для NetworkService.Как только мы сливаем имя порта из скомпрометированного средства визуализации, мы получим примитив для написания базы данных sqlite3 с полностью контролируемым путем.
Хотя поначалу это звучало не очень полезно, на самом деле вы можете использовать его, чтобы добиться выполнения кода. Я заметил, что пакетные файлы Windows - очень простительный формат файлов. Если у вас есть мусор в начале файла, он пропустит его до следующего «\ r \ n» и выполнит оттуда следующую команду. В своем эксплойте я использую его для создания файла cookies.bat в каталоге автозапуска пользователя, добавления cookie с «\ r \ n» и командой в нем, и он будет выполнен при следующем входе в систему.
В конце концов, этот эксплойт работал в среднем за 1-2 минуты и последовательно работал менее чем за 5 минут на моей машине. И я уверен, что это может быть значительно улучшено, так как я видел много ускорений от небольших изменений и различных методов. Например, MLPDS кажется даже быстрее на практике, чем вариант, который я использую.
Резюме эксплойта:
- Компромитация рендерера.
- Запустите эксплойт RIDL в процессах $ NUM_CPU-1 с различными смещениями строк кэша.
- Создайте поддельное соединение WebRTC и переключайтесь между подключенным и отключенным.
- Утечка имени порта NetworkService.
- Создайте новый NetworkContext с файлом cookie по адресу c: \ path \ to \ user \ autorun \ cookies.bat
- Вставьте файл cookie «\ r \ ncalc.exe \ r \ n».
- Дождитесь следующего входа.
Когда я начал работать над этим, я был удивлен тем, что он все еще может использоваться, хотя уязвимости были публичны некоторое время. Если вы прочтете руководство по этой теме, они, как правило, расскажут о том, как были устранены эти уязвимости, если ваша ОС обновлена, с указанием, что вам следует отключить гиперпоточность, чтобы полностью защитить себя. Сосредоточение внимания на митигации определенно дало мне ложное представление о том, что уязвимости устранены, и я думаю, что в этих статьях можно было бы более четко понять, как оставить включенным гиперпоточность.
При этом я хотел бы, чтобы вы убрали две вещи из этого поста. Во-первых, ошибки утечки информации могут быть не просто обходом ASLR. Даже если бы не зависимость от секретных имен портов, были бы утечки других интересных данных, например UnguessableTokens Chrome, куки Gmail или конфиденциальные данные в других процессах на машине. Если у вас есть идея, как найти утечки информации в масштабе, Chrome может быть хорошей целью.
Во-вторых, я долгое время игнорировал аппаратные уязвимости, поскольку они находятся за пределами моей зоны компетенции. Тем не менее, я надеюсь, что смог дать вам информацию об их влиянии с помощью этого поста, чтобы помочь вам принять решение, стоит ли отключить гиперпоточность. Существует много возможностей для изучения того, какие другие программы могут быть взломаны подобным образом, и я хотел бы видеть больше примеров применения аппаратных ошибок для преодоления границ безопасности программного обеспечения.
Источник:
Ссылка скрыта от гостей