|
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.