Chrome предал вас — любое расширение теперь способно украсть OAuth-токены и секретные ссылки

OAuth-токены, API-ключи и закрытые видео YouTube сливают посимвольно.


9090yruhh4m4y9byvscv5dbamabw9nrc.jpg

В Chrome нашли способ вытащить полный URL любой открытой вкладки даже у расширения, которому формально не давали доступ ни к вкладкам, ни к сайтам. Достаточно, чтобы у расширения было только разрешение declarativeNetRequest. Обычно его считают относительно безопасным, потому что оно связано с правилами блокировки запросов и не дает прямого чтения содержимого страниц. Но исследователь показал, что этого хватает, чтобы выведать адрес страницы посимвольно, опираясь на разницу во времени между заблокированными и разрешенными загрузками.

Ключевой элемент здесь, API declarativeNetRequest. Он позволяет расширениям добавлять динамические правила, которые блокируют запросы по шаблону. Эти правила умеют сопоставлять URL по регулярным выражениям . В Chrome заблокированный запрос обрывается сразу и возвращает ошибку net::ERR_BLOCKED_BY_CLIENT, причем практически мгновенно. А если правило не срабатывает, браузер продолжает обычную загрузку, которая занимает заметно больше времени, потому что начинаются сетевые подключения. Именно это время и становится подсказкой, которую расширение может использовать как "оракул".

Внутри Chromium поведение блокировки выглядит так, что при совпадении правила система очищает ожидающие колбэки и быстро завершает обработку с net::ERR_BLOCKED_BY_CLIENT. Для расширения это означает два разных сценария. Когда блокировка сработала, реакция быстрая, в воспроизведении разница составляла примерно 10–30 мс. Если совпадения нет, запрос идет дальше и задержка становится выше, порядка 50–100 мс и больше, в зависимости от сети и сайта.

Чтобы измерять этот эффект, расширение использует два обычных механизма, не требующих tabs permission. Во первых, оно вызывает chrome.tabs.reload, чтобы инициировать перезагрузку страницы. Во вторых, оно подписывается на chrome.tabs.onUpdated и ждет событие, где статус меняется на complete. Дальше остается просто измерить, сколько времени прошло между reload и моментом, когда вкладка "дозагрузилась". Быстро, значит запрос оборвали правилом. Медленно, значит браузер действительно пытался загрузить страницу.