Skip to content

HTML5 Canvas/getImageData and the nefarious

2009 December 18
by Aaron

This afternoon, I indulged myself by returning to my HTML5 experimentation and tinkering, toying with the canvas element by testing the waters of different functions under the HTML5 specification API.

All was good until I got to getImageData(), where I encountered an exception in console. The crux is this: I’m getting an NS_ERROR_DOM_SECURITY_ERR error when trying to run context.getImageData()

A bit about getImageData():

To obtain an ImageData object containing a copy of the pixel data for a context, you can use the getImageData() method:

var myImageData = context.getImageData(left, top, width, height);

Ultimately, I wanted to use this function to place a image on canvas and perform some direct pixel manipulation; perhaps inverse an image by first getting the image data from a context.

window.addEventListener('load', function () {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var img = new Image();

  img.addEventListener('load', function () {
    var x = 0,
      y = 0;

    ctx.drawImage(this, x, y);

    var imgd = ctx.getImageData(x, y, this.width, this.height);
    var imxpxl = imgd.data;

    for (var i = 0, n = imxpxl.length; i < n; i += 4) {
      imxpxl[i] = 255 - imxpxl[i]; // red
      imxpxl[i + 1] = 255 - imxpxl[i + 1] // green;
      imxpxl[i + 2] = 255 - imxpxl[i + 2] // blue;
      // i+3 is alpha
    }
    ctx.putImageData(imgd, x, y);
  },
  false);
  img.src = "http://www.google.ca/intl/en_ca/images/logo.gif";
},
false);

Running this code, I didn't get the results I expected. In fact, I did not think out of the ordinary was incorrect, until I checked the error console and found:

Error: uncaught exception: [Exception... "Security error"  code: "1000" nsresult: "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR)"  location: "file:///pixeldata.html Line: 16"]

Interesting - why the need to raise privileges? Am I forgetting something here? If I toss a,

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");

I end up with something yucky like this

try {
  try {
    imgd = ctx.getImageData(x, y, this.width, this.height);
  } catch(e) {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    imgd = ctx.getImageData(x, y, this.width, this.height);
  }
} catch(e) {
  throw new Error("unable to access image data: " + e);
}

but, running the code will yield:

A script from "file://" is requesting enhanced abilities that are UNSAFE and could be used to compromise your machine or data:

In this case, the code will run - but it will leave you with an impression that what you're doing is wrong.

I'm not nefarious, I swear! No intent to do harm here. I am trying to understand the reasoning and or need for raised privileges just to extract data from a context. With a write to canvas, a nefarious user could write something nasty to context, but why with getImageData?

- Aaron

9 Responses leave one →
  1. December 18, 2009

    Try it with an image on your own domain! An image from a remote domain could have security-sensitive information dependent on the user’s cookies that you don’t have access to.

    (Note: I know nothing about the code, but being able to access some other site’s data seems like it’d be a blatant security flaw, so I’m duly impressed but not really surprised that the Firefox devs realized this and blocked it)

  2. December 18, 2009

    Hi Aaron,

    I’m not on expert on Firefox’s security model, but I believe this is because drawImage from google.com makes your canvas write-only. The canvas is flagged write-only because the image is not in the same security domain as your page.

    What’s the attack vector? Not quite sure, but it might go something like:
    1) there is an image on another domain that contains sensitive information about you (could just be your profile pic, could be an image of where you live)
    2) attacker grabs cross-domain image and puts it in dom
    3) attacker uses drawImage and getImageData, and send the dump of sensitive images to a server

    Here’s a few relevant bugs:
    https://bugzilla.mozilla.org/show_bug.cgi?id=530928
    https://bugzilla.mozilla.org/show_bug.cgi?id=417836

    I found these with a quicksearch for getImageData:
    https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20getImageData

    This bugzilla quicksearch reference is super helpful:
    http://www.squarefree.com/bugzilla/quicksearch-help.html

  3. December 18, 2009

    Other people have it already — suppose your 401(k)’s portfolio graph or performance charts are at a guessable location, then I can steal them with getImageData across origins.

  4. December 19, 2009

    Of course, if cookies weren’t permitted across domains by default, this wouldn’t be a security problem at all…

  5. mrfisher permalink
    December 19, 2009

    The reason why to ask for privilege elevation with an explicit check is clear. Others have mentioned examples, please let me add another one: online banking. A (comparable) limited set of targets. Now introduce your snap-shot code via advertising into all the browsers around the world and wait for some interesting pattern to get detected. Then send the whole snapshot “home” and let some cheap hired people play OCR on your banking data. Hmmm. Should have patented that first before leaving a reply here …

  6. April 28, 2010

    what Stuart Ballard said is right,thx.

  7. May 18, 2010

    I just hit the same error, but actually, only when running a test html file “locally”…
    As soon as you put the file and access it on a simple Apache server, the problem naturally vanishes. The above explanations seem very accurate since security on a server is handled, when it’s not on a local file …

    Alain

  8. June 26, 2010

    The problem is that when loading a local html page in Firefox via file:///path/to/file it doesn’t seem to recognize if resources are on the same domain, since there is no domain. The ‘same Origin’ policy in Javascript prevents loading of external resources for security reasons. If you put your page on a local host like http://tests.local/page it will work. Another way to fix it is to go to Firefox’s config via about:config and changing the following value: security.fileuri.strict_origin_policy.

Trackbacks and Pingbacks

  1. HTML5 Canvas/getImageData and the nefarious | HTML5source.com

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS

Free WordPress Theme

WordPress主题
WordPress Themes