Blog Archives

Using IntelliJ IDEA to debug Firefox Extensions

I have been a fan of JetBrains’ IntelliJ IDEA as an IDE for many years, and with WebStorm/PhpStorm (or IntelliJ with the JavaScript plugin) JetBrain really is on their way to having a great JavaScript IDE. What is particularly impressive is how WebStorm/PhpStorm is able to parse out meaning from untyped JS and have knowledge of many of the core JS libraries.

But one problem is that they don’t debug Firefox extensions. I often use ChromeBug for this, but sometimes it’s nice to debug right in the IDE. With a little bit of hacking I found a way to update their debugger so that it can also debug Firefox extensions.

You can get the code on GitHub at WebStorm-Firefox-Connector. I plan to update it with each update of the WebStorm Firefox extension until JetBrains adds this functionality themselves. I’ve submitted the changes to JetBrains as an issue in the hope that they will incorporate my changes into the main product.

To debug extensions with WebStorm/IntelliJ, do the following:

  • Install WebStorm and let it install the Firefox debugger extension
  • Determine what version of the Firefox debugger extension you are using (look in the Add-Ons tab)
  • Download the correct branch from GitHub for your version to replace the contents of the firefox-connector@jetbrains.com directory.
  • Edit the file extensions\firefox-connector@jetbrains.com\chrome\chromeFiles\content\scripts.js to add your chrome URL root to the variable enabledChromeComponents. For example, this allows me to debug an extension named myext:
    • ·         enabledChromeComponents: ["myext"]

 

Most folks won’t care, but it’s worth pointing out that you can’t use WebStorm to debug Firebug itself since they both use JSD, which only supports one debugger client at a time. JSD2 is supposed to fix this, but sometimes I wonder if JSD2 will ever really happen.

I do some work on Firebug, and I have looked a bit into creating a multi-layer-client wrapper for JSD, but haven’t had the time to get it actually working. Besides, the JSD layer is a bit tricky. Let’s just say I’ve gotten used to wishing JSD2 were on the horizon and knowing that it probably isn’t.

 

Update 2/14/11

They have updated the debugger extension (0.4.3) with a good chunk of my changes, but unfortunately not all of them. Looks like I’ll be updating the patched version of the debug extensions for at least a while longer. You can still find the any updates at GitHub.

I was awarded a Firefox Security Bug Bounty Award!

I just received an email from the head of the Mozilla security team that I have been awarded a Security Bug Bounty Award for an sg:critical bug I found in Firefox. For those that don’t know, sg:critical is the highest level of severity and indicates the bug is an “exploitable vulnerability which can lead to the widespread compromise of many users.” That sounds pretty scary, but on the bright side sg:critical means I get the maximum bounty of $3000 (and a t-shirt :). Very cool :).

I don’t want to share more since the vulnerability hasn’t been fixed yet, but as soon as it is I’ll give a full explanation.

Update 9/27/11

The bug is (finally) fixed and has been announced as Mozilla Foundation Security Advisory 2011-43 (CVE-2011-3004), which means I can finally talk about it. The bug deals with the guts of how Firefox wraps unsecure JavaScript objects so the details are a bit complicated. People who are interested in the gritty details should follow the above link. Since the full explanation is a bit much for a blog post I’m just going to summarize it here.

In Firefox the loadSubScript function loads code into the current security context, and since it’s called from an extension the code is loaded in the secure security context. In Firefox 3.6 (and now again in Firefox 11+) any unsecure objects passed in the loadSubScript context are correctly wrapped in a XrayWrapper (XPCNWrapper in Firefox 3.6).

Wrapper ensures that secure code can’t accidently pass an unsecure object to a secure object that can be used as a privilege upgrade attack. There are surprising number ways of doing this in JavaScript without this wrapper protection.

In Firefox 4 a bug was introduced that missed adding these wrappers for loadSubScript. So the secure loaded code was handed unsecure, unwrapped objects.  If a target window (any web page) anticipated this bug they could check for the vulnerability in each user’s browser, and if they found it they could use it to do anything a Firefox extension could do (essentially gaining full access to the user’s system, files … practically everything).

See [post: Inserting JavaScript/CSS…] for one possible use case for loadSubScript (now that it is no longer a security hole).

Inserting JavaScript/CSS in a target page from a Firefox Extension

When you’re working with Firefox extensions you often want to act on the target page, accessing elements or even changing HTML, but JavaScript libraries and jQuery plugins assume that they are always working on the current scope’s global objects.

So every time you find yourself wanting to act on variables like window, document and jQuery you run into a problem.  You could insert the module into the target window using a script tag, but that may conflict with the target window’s JS.

A better solution is to load another instance of these libraries in your own scope tied to the target window’s global variables. One approach is to eval the window inside a context that has remapped the window and document element.

The following code demonstrates this given a passed target window.


createTargetScripts: function(targetWindow) {
   // Create the scripts we will use on the target window, we create them in a closure so they will
   // have the target window and document (but our privilege, and the target objects they use will actually be wrappers).

   (function() {
      var window = targetWindow;
      var document = targetWindow.document;
      eval(evalStringForURL('libs/jquery.js'));
      var jQuery = targetWindow.jQuery;          // Add jQuery to local scope for jQuery plugins
      eval(evalStringForURL('libs/jquery.tmpl-master0405.js'));
      eval(evalStringForURL('libs/jquery.qtip.js'));

   })();

   // Even though the jQuery is on the wrapper, that wrapper may be used by other extensions
   targetWindow.targetJQ = targetWindow.jQuery.noConflict(true);

   } ,
   readURLSync: function(url) {
      var data = myExtensionJQ.ajax({
         url: url,
         async: false,
         dataType: "text",
         mimeType: 'text/plain; charset=x-user-defined'
         }).responseText;
      return data;
   },

   // Add sourceURL so debuggers will know what source file to use
   evalStringForURL: function(url) {
      var evalStr = this.readURLSync(url);
      var sourceURLStr = "//@ sourceURL=" + url;
      return evalStr + sourceURLStr;
   },

For CSS you can do even better. Instead of inserting the CSS into the target page you can load it as a “user sheet,” making it available in all pages. If you want to override existing styles in the target page you just use a “!” in your style. Here is the code:


var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
   .getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"]
   .getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(url, null, null);
   sss.loadAndRegisterSheet(uri, sss.USER_SHEET);

FYI, Another Firefox-specific approach for loading the JS libraries with a different context is to use loadSubScript, but a bug in Firefox 4 broke this. I’ve documented the bug at https://bugzilla.mozilla.org/show_bug.cgi?id=653926. Unfortunately, you can’t actually view the bug report – it was restricted because it exposes a potential Firefox security vulnerability.

Update 6/15/11

Apparently the bug I mentioned above exposes a severe security vulnerability since I was awarded a Firefox Security Bug Bounty Award. See [post: Firefox Security Bug Bounty…].

%d bloggers like this: