Closed Bug 298255 Opened 20 years ago Closed 20 years ago

Stand-alone applications can run arbitrary code through Firefox

Categories

(Core :: Security, defect)

defect
Not set
critical

Tracking

()

RESOLVED FIXED

People

(Reporter: mikx, Assigned: dveditz)

References

(Depends on 1 open bug)

Details

(Keywords: fixed-aviary1.0.5, Whiteboard: [sg:fix] Bug details embargoed until August 1, 2005)

Attachments

(4 files, 1 obsolete file)

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4 Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4 Most media types that can be viewed in Firefox using an embedded plugin, can also be viewed in a stand-alone application. This applies to the most common audio/video media types like ram/rpm/wmv/mov/avi, document formats like pdf and multimedia formats like swf (flash). The stand-alone programms can (as every other desktop application) open URLs in Firefox, usually be passing the URL to the operation system and invoking the standard browser. The URL calls are (unlike when embedded) not checked at all. A stand-alone mediaplayer can open chrome: and javascript: urls. While this is expected behavior, it turns into a security risk when looking at the fact, that it is easy to force that a media file gets opened in the stand alone programm instead of embedding it. Usually it is enough to set Content-Disposition header to type "attachement". This will result in a file download dialog which most people will accept, since many websites use this as a valid feature (e.g. for pdf downloads). Some video players (e.g. Quicktime) support dedicated formats to force that a video gets played in the stand-alone player - mostly due the fact that only the stand-alone quicktime player supports real fullscreen playback. The problem is, that many media container formats (e.g. smil) and most multimedia formats (e.g. swf) allow to automaticly open URLs by several scripting languages or other mechanisms. That means scripting commands coming from an untrusted source can automaticly invoke a desktop programm and then re-invoke Firefox to run arbitrary code by opening a chrome: url and then a javascript: url (to get universal xpconnect). One could argue, that this is a problem of the media players, but the media players are (usually) secure in handling the various containers formats - they just assume it is safe to throw urls of any kind at the default operation system webbrowser. And in case of Firefox, it's not. To proof this theory, i looked at the various file formats and players. I found a reproducable way in the handling of stand-alone flash (swf) files. The following peace of action script could be used to run arbitrary code from an swf file in a stand alone player: SWFAction("a=this.geturl('chrome://browser/content/browser.xul');b=this.geturl('javascript:alert(document.location);');")); There are some timing issues with this demo (when the xul page loads too slow) you usally have to try 2-3 times and re-start the browser after each try. I am not so good in flash, there are probably ways to make that more stable. The good news is, that flash does not ship with a stand-alone player by default, it only comes with the flash development environment or from third partys. Anyway, bad news is that it proofs the theory. Another proven way to open a chrome url is the quicktime player (using <a href> in a smil file) - and since the number of ways to manually and automaticly open URLs from media formats are literally endless (real, windows media, quicktime all support multiple ways of 'in-stream' url encodings, smil supports timed hyperlink events, acrobat reader supports javascript, etc) i strongly believe that there are many more ways. Is there any valid use for desktop applications invoking a chrome file and/or opening a javascript url in the context of another website? Shouldn't it be safe to throw URLs at Firefox in any order - especially when considering that many third party developers don't know about privileged xul? Reproducible: Always
It seems nobody takes care of this right now - still unconfirmed after a week. I added a test case that shows an automated exploit of this bug. As described in my initial post formats like QuickTime can automaticly open the stand-alone player from within an embedded browser - it only requires a special target property called "quicktimeplayer". The QuickTime player can run SWF files and those can open chrome: and javascript: urls. Putting all this together you get a fully running exploit. The demo still has some timing issues, but should work properly in about 40% of the attempts. Tried that on three different machines. Restart the browser and close Quicktime after a failed attempt. Raising the severity to critical since it's now fully working remote code execution.
Severity: normal → critical
Status: UNCONFIRMED → NEW
Component: General → Security
Ever confirmed: true
Flags: blocking1.8b3+
Flags: blocking-aviary1.0.5+
Product: Firefox → Core
Whiteboard: [sg:fix]
Version: unspecified → Trunk
This is doing something other than the normal opening a URL from an external application. When opened from the OS each URL is going to get a new window (or tab depending on pref settings), and in that situation the context for javascript urls will be the harmless about:blank rather than the previous chrome url. This testcase demonstrates that's not the case. Are these URLs opened through the plugin interface? I thought bug 280664 stopped the loading of chrome: from plugins?
(In reply to comment #3) > This is doing something other than the normal opening a URL from an external > application. When opened from the OS each URL is going to get a new window (or > tab depending on pref settings) Not every time. Using flash you can open two urls more or less at the same moment and that results in opening them in the same browser window (maybe just a timing issue). Other browser (e.g. IE) do open two new windows. Some other applications are at least able to open one url in an exesting window - usually the currently active window/tab - this would lead to cross domain scripting (e.g. to steal cookies): 1. Open the stand-alone quicktime player 2. Do a javascript location.replace to "target.domain" in the opening page 3. Invoke the existing window with a javascript: url in the context of "target.domain" This seems to be a window naming thing (e.g. it works when clicking a link in an external application which targets "_parent"). It only works the first time. After that you always open new windows unless you restart the browser. > This testcase demonstrates that's not the case. Are these URLs opened through > the plugin interface? I thought bug 280664 stopped the loading of chrome: from > plugins? When you play the SWF file in an embedded player, the patch for 280664 kicks in. But in this case the OpenURL commands comes from the stand-alone player / operation system and circumvents it.
(In reply to comment #3) > This is doing something other than the normal opening a URL from an external > application. When opened from the OS each URL is going to get a new window > (or tab depending on pref settings) True for the trunk: the pref browser.link.open_external is set to 3 in Firefox (new tab) and 2 in Suite (new window). But on the aviary/1.7 branches it was set to 1 -- reuse the currently open window. I always seem to get the JS url to open first so I don't quite see the exploit, but I imagine it would be trivial to put a delay in the flash script to make sure the chrome URL has opened first. In any case a javascript URL could be used to steal information from the currently opened page. What if we do something like the solution to the history.back() bug and explicitly load about:blank first to clear the plate when loading an external URL?
Whiteboard: [sg:fix] → [sg:fix] [cb] eta?
Assignee: nobody → mikx
In addition to putting a context-clearing about:blank load in front of any javascript: or data: url, there's no need to allow chrome: urls to be loaded into a browser window from external programs at all. People who have built non-browser chrome applications launch them with "-chrome chrome:/mychrome/content/", not "-url chrome:/mychrome/content/"
Yeah, sounds reasonable to me. Should be pretty easy to do, even. You hacking on this dveditz?
Assignee: mikx → dveditz
This is a Suite issue as well.
Flags: blocking1.7.9+
Attached patch aviary 1.0.x patch (obsolete) — Splinter Review
This works for aviary.
Attachment #188417 - Flags: superreview?(jst)
Attachment #188417 - Flags: review?(mconnor)
Attachment #188417 - Attachment is obsolete: true
Attachment #188423 - Flags: superreview?(jst)
Attachment #188423 - Flags: review?(mconnor)
Attachment #188423 - Flags: approval1.7.9?
Attachment #188423 - Flags: approval-aviary1.0.5?
Comment on attachment 188423 [details] [diff] [review] incorporating mconnor's suggestions >+ try { >+ if (makeURL(uriToLoad).schemeIs("chrome")) { >+ dump("Preventing external load of chrome: URI\n"); lets go a step farther and add "To load chrome URIs, you must use the -chrome switch.\n" here >- .loadURI(url, nsIWebNavigation.LOAD_FLAGS_NONE, referrer, >+ .loadURI(url, loadflags, referrer, > null, null); nit: there's no need for the args to be split onto two lines now, you fixed this in the previous case >+ // Before going any further vet loads initiated by external programs. >+ if (aLoadType == LOAD_NORMAL_EXTERNAL) { >+ // clear the decks to prevent context bleed-through (bug 298255) >+ rv = CreateAboutBlankContentViewer(); shouldn't you be checking rv here? >+ // Disallow external chrome: loads targetted at content windows >+ PRBool isChrome = PR_FALSE; >+ if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) { >+ return NS_ERROR_FAILURE; >+ } this should probably go before the previous block, since there's no point in creating the new content viewer if we're going to fail here r=me with those
Attachment #188423 - Flags: review?(mconnor) → review+
Attachment #188417 - Flags: superreview?(jst)
Attachment #188417 - Flags: review?(mconnor)
Comment on attachment 188423 [details] [diff] [review] incorporating mconnor's suggestions sr=jst
Attachment #188423 - Flags: superreview?(jst) → superreview+
Comment on attachment 188423 [details] [diff] [review] incorporating mconnor's suggestions a=chofmann for the branches
Attachment #188423 - Flags: approval1.7.9?
Attachment #188423 - Flags: approval1.7.9+
Attachment #188423 - Flags: approval-aviary1.0.5?
Attachment #188423 - Flags: approval-aviary1.0.5+
Whiteboard: [sg:fix] [cb] eta? → [sg:fix] [cb] patch ready to land
Landed on aviary branch
Whiteboard: [sg:fix] [cb] patch ready to land → [sg:fix] need 1.7 branch and trunk
Seeking Neil's r= on the navigator.js portion which was not reviewed as part of the aviary branch patch
Attachment #188483 - Flags: superreview+
Attachment #188483 - Flags: review?(neil.parkwaycc.co.uk)
Attachment #188483 - Flags: approval1.8b3+
v.fixed on aviary with Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.9) Gecko/20050706 Firefox/1.0.5. Still waiting to land on the Trunk and 1.7 branch, where it will need to be verified as well.
Comment on attachment 188483 [details] [diff] [review] trunk version (incl suite) r=mconnor
Attachment #188483 - Flags: review?(neil.parkwaycc.co.uk) → review+
Not quite sure what to do about mozilla 1.7.x. This fix builds on the nsIBrowserDOMWindow::OPEN_EXTERNAL stuff that was added to aviary but not the suite until sometime on the trunk.
Fix checked into trunk. Neil has some concerns that this blocks the ability to have a chrome: home page and is working on an alternate patch for the "startup" part of this. That approach will also work for the 1.7 branch to prevent loading chrome urls from external, but not solve the javascript: problem unless we're ok just blocking those outright.
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
Whiteboard: [sg:fix] need 1.7 branch and trunk → [sg:fix] need 1.7 branch
+ if (makeURL(uriToLoad).schemeIs("chrome")) { is that sufficient? For example, about:config also has chrome privileges. is that taken care of by the other checks?
Actually it turns out that suite already (tries to, but my Windows doesn't recognise it) associate external chrome: URLs with the -chrome option.
Group: security
Blocks: 299444
Blocks: 300114
Group: security
Adding distributors
Suite 1.7 is OK on this one: the default behavior is to open external links in new windows so javascript: urls are always run in an about:blank context. The trunk version of the suite has the option to reuse the most recent window (still not the default), but the context-clearing fix landed on the trunk.
Whiteboard: [sg:fix] need 1.7 branch → [sg:fix] Bug details embargoed until July 20, 2005
Filed bug 300800 on some issues I think that patch has...
Depends on: 300800
Looks like the fix to this bug caused bug 301073. /be
Comment on attachment 188483 [details] [diff] [review] trunk version (incl suite) Mozilla/Suite uses -chrome for chrome:// URL protocol so I claim it doesn't need the startup patch so please back it out to fix the xpfe version of bug 301073.
Whiteboard: [sg:fix] Bug details embargoed until July 20, 2005 → [sg:fix] Bug details embargoed until August 1, 2005
Group: security
More followups: bug 305374, bug 305269, bug 304690.
Flags: testcase+
Depends on: 310793
Flags: in-testsuite+ → in-testsuite?
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: