5th Feb 2003 [SBWID-5973]
COMMAND
Opera mutiple vulnerabilities
SYSTEMS AFFECTED
Opera 7
PROBLEM
Thanks to GreyMagic Software security advisories :
[GM#002-OP] http://security.greymagic.com/adv/gm002-op/
" Many thanks to Tom Gilder for his excellent help in researching this
vulnerability. "
- And -
[GM#003-OP] http://security.greymagic.com/adv/gm003-op/
[GM#004-OP] http://security.greymagic.com/adv/gm004-op/
[GM#005-OP] http://security.greymagic.com/adv/gm005-op/
[GM#006-OP] http://security.greymagic.com/adv/gm006-op/
Problem 1 [GM#002-OP]
=========================
Version 7 brings many long-awaited features such as proper DOM support
and an improved rendering engine. However, Opera seems to have
neglected one of the most important aspects in any browser today, its
default cross-domain security model.
Discussion:
===========
All browsers with Javascript support deploy a cross-domain security
model, which, in essence, attempts to prevent documents from one domain
to access other documents in different domains.
Opera 7 deployed a fundamentally different approach to cross-domain
security, a caller-based model, rather than the origin-based model
deployed in other browsers. The vulnerability is comprised of three
different flaws in that model:
* Functions in different domains can be accessed and executed.
* Functions are being executed under the caller's domain credentials and not
in their originating domain.
* It is possible to override properties and methods (both native and user-defined) in other windows.
The first flaw means that a window in one domain is able to execute
functions in a window that's in a different domain. This flaw in itself
is not a big threat because of the second flaw, which means that even
if a function in the victim window is executed, it is executed with the
attacker's credentials, and therefore unable to access the victim's
document.
The second flaw means that if the attacker can get the victim to
execute a function, it will run under the victim's credentials. And
because of the first flaw, the victim will have no problems accessing a
malicious function created by the attacker.
The third, and most devastating flaw means that the attacker is able to
trojanize native methods in the victim window with his own code and
simply wait for the victim to execute it.
With these three flaws combined, it becomes extremely easy to exploit
any document that uses some scripting, including local resources in the
file:// protocol. Being able to access local resources in Opera means
that the attacker would be able to:
* Read any file on the user's file system.
* Read the contents of directories on the user's file system.
* Read emails written or received by M2, Opera's mail program.
* And more...
Exploit:
========
A perfect candidate for exploitation is Opera's own Javascript console,
which arrives in the form of three separate files in Opera's
installation directory.
The file "console.html" makes a very early call to the native method
"setInterval", which can be overridden by an attacking window. This
scenario does not require any user interaction.
<script language="jscript">
var oWin=open("file://localhost/console.html","","");
oWin.setInterval=function () {
alert("Access to local resource achieved: "+oWin.location.href);
}
</script>
The "file://localhost/" URL appearing in this sample is a convenient
method provided by Opera in order to access the selected directory
(Opera's home by default).
Demonstration:
==============
We put together two proof-of-concept demonstrations:
* Simple: Reads cookies from a few well-known sites and demonstrates access
to a local resource.
* GreyMagic Opera Disk Explorer: Browse your entire file system using this
explorer-like tool, which takes advantage of this vulnerability in order to
access local resources.
They can both be found at http://security.greymagic.com/adv/gm002-op/.
Problem 2 [GM#003-OP]
=========================
Version 7 brings many long-awaited features such as proper DOM support
and an improved rendering engine. Among the useful new features Opera
added a shiny new Javascript console. The console is mainly used by
developers in order to efficiently track down exceptions in running
scripts.
Discussion:
===========
Opera's Javascript console is using three html files residing in
Opera's installation directory. The most important of them is
"console.html", which contains all the logic behind the console.
The console lists unhandled exceptions that are thrown during the life
of a session. Javascript can throw custom exceptions using the "throw"
statement and Opera also adds its own way to create debug messages with
the "opera.postError" method.
In order to display clickable URLs properly, Opera does some formatting
on the thrown exception message to turn them into links:
newmsg = msg.replace( /</g, "<" ).
replace( />/g, ">" ).
replace( /https?:\/\/\S+/g, create_link ).
replace( /file:\/\/(?:\S|(?:[ ](?=[^\n\r]*\.)))+/g, create_link );
The first two lines supposedly handle the safety of this string, so it
wouldn't contain HTML. The last two lines are meant to transform
strings that appear like URLs into actual links. Unfortunately, each of
these last two lines contains an obvious way for an attacker to inject
his own attributes to the link. By doing so, the attacker can gain
access to the file:// protocol, which, among others, have the following
implications:
* Read any file on the user's file system.
* Read the contents of directories on the user's file system.
* Read emails written or received by M2, Opera's mail program.
The first vulnerable regular expression is /https?:\/\/\S+/g, it's
trying to match anything starting with "http://" or "https://" and
keeps consuming characters as long as they aren't whitespace. This
regular expression does not check for the existence of quotes, which
are the delimiters of the "href" attribute in the resulting link, and
therefore opens up a way to add additional attributes (spaces between
attributes are not mandatory).
The second vulnerable regular expression is /file:\/\/(?:\S|(?:[
](?=[^\n\r]*\.)))+/g, it's trying to match anything starting with
"file://" followed by a non-whitespace character or a regular space, as
long as a dot appears and no line breaks appear after it. The same
mistake is made again; quotes can be used to add additional attributes
to the link.
Being able to add arbitrary attributes to a link may seem innocent, but
with a little manipulation it leads to the execution of arbitrary
script code. The "style" attribute in most elements, for example, may
contain properties such as "background-image", which normally point to
a URL. That URL can be "javascript:[code]", which will be executed in
the context of the console (file:// protocol).
Exploit:
========
A simple exploit of the first regular expression:
open("file://localhost/console.html","","");
opera.postError("http://\"style=\"background-image:url('javascript:alert(location.href)')\"");
A simple exploit of the second regular expression:
open("file://localhost/console.html","","");
opera.postError("file://\"style=\"background-image:url('javascript:alert(location.href)')\".");
Demonstration:
==============
We put together two proof-of-concept demonstrations:
* Simple: Demonstrates how the poisonous debug message is being inserted.
* GreyMagic Opera Disk Explorer: Browse your entire file system using this
explorer-like tool, which takes advantage of this vulnerability in order to
access local resources.
They can both be found at http://security.greymagic.com/adv/gm003-op/.
Problem 3 [GM#004-OP]
=========================
Opera 7, just like any other browser, supports a considerable amount of
image formats. Images are normally embedded in HTML documents but they
can also be accessed directly via the browser.
Discussion:
===========
By examining the HTML Opera produces when it displays a single image,
it becomes obvious that Opera doesn't bother to do any formatting on
the provided URL. Luckily though, Opera automatically encodes most
characters in the URL, so access to other domains via this flaw becomes
impossible.
However, URLs to local files (file:// protocol) do not get encoded and
therefore cannot evade the very basic form of XSS:
file://path/to/image.jpg?">Arbitrary HTML here.
And to make this even more comfortable for attackers, Opera provided an
easy way to refer to its own installation directory -
file://localhost/. So instead of searching for default images in the
OS, an attacker can simply refer to file://localhost/images/file.gif,
one of the few images Opera ships by default, and enjoy the following
abilities:
* Read any file on the user's file system.
* Read the contents of directories on the user's file system.
* Read emails written or received by M2, Opera's mail program.
* And more...
Note: the same applies to embeddable media, such as SWF.
Exploit:
========
open("file://localhost/images/file.gif?\"><script>alert(location.href);</script>","","");
Demonstration:
==============
We put together two proof-of-concept demonstrations:
* Simple: Demonstrates how a single local image can be exploited.
* GreyMagic Opera Disk Explorer: Browse your entire file system using this
explorer-like tool, which takes advantage of this vulnerability in order to
access local resources.
They can both be found at http://security.greymagic.com/adv/gm004-op/.
Problem 4 [GM#005-OP]
=========================
Like any other browser, Opera supports the "history" object, which
makes it possible to navigate through the browser history by exposing
the "back", "forward", and "go" methods.
Discussion:
===========
Opera exposed a little more than a few methods on the history object.
It also exposes two properties, "next" and "previous". Unlike the
methods mentioned above, these properties contain actual URLs.
This means that when a user navigates to a website, the owner can
easily check and log where the user had last been, and even where he
went right afterwards (in case the user goes back in history),
regardless of whether that previous URL referred to the owner's web
site or not.
Notice that "history.previous" is not the same as the "HTTP_REFERER"
header. It will return the last URL even if it was not the direct
referrer to the current URL, which makes Opera's "Enable referrer
logging" configuration option completely pointless.
That's a serious breach of privacy, which Opera seemed to have
implemented intentionally.
Exploit:
========
The following code demonstrates how to retrieve these properties:
alert("Last URL: "+history.previous+".\nNext URL: "+history.next+".");
Demonstration:
==============
A proof-of-concept demonstration of this issue is available at
http://security.greymagic.com/adv/gm005-op/.
Problem 5 [GM#006-OP]
=========================
The new browser features a very useful Javascript console, which uses a
few methods Opera implemented in the "opera" object.
Discussion:
===========
These methods appear in the comments of the "console.html" file as
follows:
* opera.errorIndex():
Returns the index of the last error message. This index is
monotonically increasing (which limits us to about 2^53 errors per
Opera session).
* opera.errorMessage(i):
Returns the error message at index i. The value returned may be #f, if
that message has been flushed from the cache.
Opera hadn't bothered to restrict these methods to certain credentials
and they are available for any web page to use. At first glance this
doesn't appear to be a big deal, but a short inspection of the
generated error messages reveals that each of them contains the URL
that threw the exception.
In practice, this means that a web page can extract a list of all URLs
the user had visited and that threw any exceptions. And since Opera
pretends to be Internet Explorer by default, it often encounters errors
in web pages. Harvesting visited URLs had never been this simple.
Exploit:
========
The following code will generate a list of visited URLs:
var sMsg,
sFinal="",
iLen=opera.errorIndex();
for (var iErr=0;iErr<iLen;iErr++) {
sMsg=opera.errorMessage(iErr);
if (sMsg && /(https?:\/\/\S+)/i.test(sMsg)) sFinal+=RegExp.$1+"\n";
}
alert(sFinal);
Demonstration:
==============
A proof-of-concept demonstration of this issue is available at
http://security.greymagic.com/adv/gm006-op/.
SOLUTION
Solution 1 [GM#002-OP]
=========================
Opera was notified of a variation of this issue on 14-Nov-2002, but
appareantly failed to understand the core issues and only patched one
symptom of the problem (it was possible for foreign windows to simply
set event handlers in Beta 1).
In the meantime, until a patch becomes available, disable Javascript by
going to: File -> Preferences -> Multimedia, and uncheck the "Enable
JavaScript" item.
Solution 2 [GM#003-OP]
=========================
Fortunately, this vulnerability can be solved manually:
* Edit the file "console.html", which resides in Opera's installation
directory.
* Line 52 should read: m.replace( /\\/g, "\\\\" ) +
* Replace it with: m.replace( /\\/g, "\\\\" ).replace(/"/g,""") +
Solution 3 [GM#004-OP]
=========================
Until a patch becomes available, disable Javascript by going to: File
-> Preferences -> Multimedia, and uncheck the "Enable JavaScript" item.
Solution 4 [GM#005-OP]
=========================
Hopefully, Opera will reconsider these properties and remove them from
the history object. Until then you may prefer to disable Javascript by
going to: File -> Preferences -> Multimedia, and uncheck the "Enable
JavaScript" item.
Solution 5 [GM#006-OP]
=========================
Until a patch becomes available, disable Javascript by going to: File
-> Preferences -> Multimedia, and uncheck the "Enable JavaScript" item.
Update (06 February 2003)
======
Opera 7.01 is out already, fixing the vulnerabilities GreyMagic
reported.