
Повышение привилегий Firefox через IPDL content-to-parent (N-day, bug 2054416): поддельный PDocumentChannel с RemoteTypeOverride -> размещение в процессе privilegedabout, через инъекцию send-path mojo-port из скомпрометированного content-процесса
PoC-эксплойт для побега из песочницы в Firefox 149.0a1 nightly (2fbc0748c4,
до исправления). Скомпрометированный content-процесс подделывает IPDL-сообщение,
из-за чего parent-процесс загружает страницу в привилегированный
(privilegedabout) процесс.
Это побег из песочницы второго этапа, предназначенный для использования после RCE в content-процессе (например, CVE-2026-2796).
Parent-процесс десериализует nsDocShellLoadState из IPDL-сообщений
content→parent. Уязвимая сборка не отклоняет поле RemoteTypeOverride,
устанавливаемое content-процессом, поэтому content может выбирать, в процессе
какого типа окажется навигация.
Исправление (коммит 3ec5c71b41bb, «Validate RemoteTypeOverride») заставляет
конструктор nsDocShellLoadState отклонять любое переопределение при загрузке,
инициированной content-процессом.
Когда переопределение учитывается — загрузка документа about:blank, верхний
уровень контекста — IsolationOptionsForNavigation устанавливает тип удалённой
загрузки в значение переопределения, и страница попадает в привилегированный
процесс. Граница песочницы нарушена.
Переопределение передаётся через PNecko::PDocumentChannel — сообщение, которое
каждый content-процесс отправляет при каждой загрузке документа
(DocumentChannelCreationArgs.loadState — это nsDocShellLoadState).
Доставка — самая интересная часть: прямая запись в IPC-сокет молча отбрасывается, поскольку IPDL-сообщения теперь передаются через mojo-порты. Вместо этого PoC управляет реальным путём отправки из JavaScript через нативные вызовы (используя примитив funcref из CVE-2026-2796):
operator new — выделение блока кучи под IPC::MessageIPC::Message::Message(routing, type, capacity, flags) — placement-конструкторPickle::WriteBytes — добавление поддельной полезной нагрузкиMessageChannel::Send на PContent-канале — mojo-обрамление, маршрутизация
портов и порядковые номера обрабатываются нативноПолезная нагрузка (создаётся forge.py) содержит
RemoteTypeOverride = "privilegedabout", URI about:blank, нулевой
(null) principal и значения, утёкшие из рантайма (id BrowsingContext,
TriggeringRemoteType).
./irun
Логи parent-процесса (MOZ_LOG=ProcessIsolation:5,DocumentChannel:5) показывают
переключение процесса в привилегированный процесс:
V/ProcessIsolation using remote type override (privilegedabout) for load
I/ProcessIsolation Process Switch: Changing Remoteness from 'webIsolated=http://127.0.0.1' to 'privilegedabout'
3ec5c71b41bb «Validate RemoteTypeOverride»| Файл | Назначение |
|---|
privesc.html | PoC-страница, запускается внутри скомпрометированного content-процесса |
forge.py / forge.json | сборка поддельного IPDL-сообщения (с самопроверкой) |
wasm-bytes.js | примитивы первого этапа: произвольное чтение/запись, вызовы funcref |
mdrive.py / mdrive2.py | marionette-обвязка для запуска и управления Nightly |
irun | инструментированный запуск: lldb attach к parent + доказательства через MOZ_LOG |
profile.user.js | настройки профиля Firefox (fission включён, dump включён) |
parse_dc.py | побайтово точный парсер перехваченных сообщений DocumentChannel |
scan_sentinels.py / extract_fields.py | сканеры карты полей для перехваченных данных |