SECCOM Labs logo
Resources for Secure
Software Engineering
from Security Compass

Hacking Access Me

By Tom Aratyn on April 16, 2009, about: Developers, Other Platforms, Security, exploit-me

The Exploit Me For Fun and Profit presentation at SecTor was a great chance to let even more people know about the exciting Exploit Me work being done at Security Compass. Unfortunately there wasn’t quite enough time to give a full overview on how to hack Access Me to implement new evaluation methods so we’re presenting that information here.

We’re going to start by breaking down what is an .xpi file is and some Mozilla technologies, then move on to discussing where the code that we want to change lives, and then finally we’ll analyze an existing evaluation function.

Firstly, let’s start with the Access Me .xpi file that you get when you download from addons.mozilla.org. XPI is a Mozilla file format which is similar to a jar in that it’s basically a ZIP file with some code inside. However the format of an .xpi is different from a .jar (check out the Mozilla Development Center for more info on the .xpi format).

What really concerns us is the content directory. That’s where all the code that makes Access Me run lives. The code is roughly into two types of files: .xul files (defining the user interface) and .js files (the Javascript files which define functionality).

Many people find it surprising, but yes, all of the Exploit Me Add-ons and much of Firefox is written in JavaScript. JavaScript is a very interesting and oft misunderstood language, I suggest reading Douglas Crockford’s essays and the MDC’s reintroduction to JavaScript.

Specifically, what concerns us are the evaluators.js, ResultsManager.js, and AttackRunner.js. evaluators.js holds functions for doing the evaluation of whether a test succeeded. ResultsManager.js defines an object for collecting the results from the evaluations. AttackRunner.js defines the code for running an actual attack.

Let’s start with the evaluators since that’s what’s going to let us do custom evaluation of the results. An evaluator is a JS function that takes a single parameter, a StreamListener, and returns an array of Results. The StreamListener parameter has two interesting properties:

  • data - the raw source code of a web page after an attack
  • attackRunner - an AttackRunner is an object responsible for running the actual attack (it’s documented in attackrunner.js). It’s useful because it has lots of information on the attack itself. For example it has the following properties:
    • channel - an object which has information on the http connection that happened. It’s documented at http://mxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/public/nsIHttpChannel.idl and http://mxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIChannel.idl
    • httpMethod - the http method, or verb, used in the attack
    • typeOfAttack - indicates what kind of attack happened (Cookie? Cookie & Get? Post?). Check against AttackRunner.prototype.ATTACK_* to check what kind of attack took place.
    • nameParamToAttack - the parameter that got dropped.
    • Here’s the Access Me evaluation function that checks for the HTTP response code and returns a warning if the response code is 200 and a pass otherwise:

      function checkForServerResponseCode(streamListener){
      var stringEncoder = getHTMLStringEncoder();
      var nsiHttpChannel = streamListener.attackRunner.channel.QueryInterface(Components.interfaces.nsIHttpChannel);
      try{
      if ((nsiHttpChannel.responseStatus === undefined || nsiHttpChannel.responseStatus === null)){
      return null;
      }
      else {
      var result;
      var responseCode = nsiHttpChannel.responseStatus;
      var displayString = stringEncoder.encodeString(responseCode.toString()) + ” ” +
      stringEncoder.encodeString(nsiHttpChannel.responseStatusText);
      if (responseCode == 200) {
      result = new Result(RESULT_TYPE_WARNING, 100, “Got access to a resource that should be protected. Server response code: ” + displayString + “. “);
      }
      else {
      result = new Result(RESULT_TYPE_PASS, 100, “Did not access protected resource. Server response code: ” + displayString + “. “);
      }
      }
      return [result];
      }
      catch(err){
      Components.utils.reportError(err);
      return false;
      }
      }

      Let’s go through it a couple lines at a time:

      var stringEncoder = getHTMLStringEncoder();

      A StringEncoder lets us encode potentially dangerous data (like the kind that comes back from an attack) so that we can display it to the user in a report.

      var nsiHttpChannel = streamListener.attackRunner.channel.QueryInterface(Components.interfaces.nsIHttpChannel);

      We want to get easy access to information on the http connection, or channel, so we get a reference to it. The QueryInterface is a necessary quirk of the Mozilla XPCOM type system it’s basically checking to make sure that that object implements the specified interface).

      if ((nsiHttpChannel.responseStatus === undefined || nsiHttpChannel.responseStatus === null)){
      return null;
      }

      If there is no status in the channel then die.

      var result;
      var responseCode = nsiHttpChannel.responseStatus;
      var displayString = stringEncoder.encodeString(responseCode.toString()) + ” ” +
      stringEncoder.encodeString(nsiHttpChannel.responseStatusText);

      Here we grab the response status code and text and encode it to make sure that we can display it in the report.
      if (responseCode == 200) {
      result = new Result(RESULT_TYPE_WARNING, 100, “Got access to a resource that should be protected. Server response code: ” + displayString + “. “);
      }
      else {
      result = new Result(RESULT_TYPE_PASS, 100, “Did not access protected resource. Server response code: ” + displayString + “. “);
      }

      Here we check the response code and create a result. The result constructor gets a constant indicating what type of result it is (pass, warning, fail), an importance indicator (used in sorting), and a string to display to the user in the report to explain the result.

      return [result];

      Finally we return the result as an array. All evaluators return arrays (even if they’re just returning one item).

      There’s just one final thing: we need to make sure that the evaluator is used! Currently Access Me does not recognize new evaluators automatically. For that you need to register it with the ResultManger in the constructor by calling:

      this.addSourceEvaluator(yourNewEvaluatorName);

      And that’s it! You should now be able to do custom evaluations using Access Me. If you have questions we’re glad to help just email us at tools@securitycompass.com. Happy Hacking!