Bug 20034 - canvas getImageData opens security whole for code
canvas getImageData opens security whole for code
Status: CLOSED WONTFIX
Product: HTML WG
Classification: Unclassified
Component: HTML Canvas 2D Context
unspecified
All All
: P2 critical
: ---
Assigned To: rcabanie
HTML WG Bugzilla archive list
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-11-21 05:52 UTC by Klaus Bertram
Modified: 2012-11-22 05:22 UTC (History)
6 users (show)

See Also:


Attachments
sample image and html side (716 bytes, application/zip)
2012-11-21 05:52 UTC, Klaus Bertram
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Klaus Bertram 2012-11-21 05:52:50 UTC
Created attachment 1249 [details]
sample image and html side

With the canvas it is possible to read byte data out of an image.
Images himself can come from different urls (hosts) without restriction.
What happens when someone fill an image with code values as pixel data, load the image into an canvas and interpret it?
He could execute code without any knowledge of any security prevention because the "code" are an image.
What I've done is simple:
1. create an image where the pixel are the color representation of
  window['alert']('xss')
  this could be an gif, png... It depends of the color interpolation in the resulting image.
2. load the image into a web side
3. create an canvas object an put the image inside.
4. read the byte data of the canvas and cast it as string to eval
Eh viola

This is small js for it:
var img=new Image();
img.onload=function()
{
var ca = document.createElement('canvas');
ca.width=this.width;
ca.height=this.height;
var ctx = ca.getContext('2d');
ctx.drawImage(this,0,0);
var a="",d=ctx.getImageData(0, 0,this.width, this.height).data;
for(var i=0;i<d.length;i++){
if(d[i]<255) a+=String.fromCharCode(d[i]);
}
eval(a);
}
img.src="exploid.gif";
Comment 1 Boris Zbarsky 2012-11-21 06:02:19 UTC
I'm going to regret this...

How is this different from doing an XMLHttpRequest to get the data as a string and calling eval()?

Seems like the real problem here is calling eval() on a string of unknown provenance, no?
Comment 2 Klaus Bertram 2012-11-21 06:10:17 UTC
It is very different, becouse here normal firewalls and intrusion detection systems has a chance to interpret and revert the text (code), but as an image not
Comment 3 Boris Zbarsky 2012-11-21 06:38:45 UTC
> becouse here normal firewalls and intrusion detection systems has a chance to
> interpret and revert the text (code)

How, exactly?  All they know is the browser is doing an HTTP GET.  The server returns an image.  What exactly is the firewall detecting?
Comment 4 Klaus Bertram 2012-11-21 07:12:21 UTC
If you have some intrusion detection systems, virus scanner and so on they try to find in every request signatures of possible code. That's one of the points why exploit kits obfuscate and encrypt their code. With this it is not needed any more and the images can come from any legal image library.
Comment 5 Boris Zbarsky 2012-11-21 15:44:13 UTC
Ah, so your concern is that the code signature will not be found because the image encoder obfuscates it?

How is that different from any other obfuscation method applied to code that's fetched with XHR?

What's the attack model here?  Is the code calling eval() actively trying to smuggle in code somewhere, such that it's cooperating with the server the image is coming from to do so?  Or is the server an attacker while the code calling eval() is not trying to do anything bad?
Comment 6 Klaus Bertram 2012-11-21 16:20:28 UTC
Yes that's my concern because:
Every Browser can load images from elsewhere without restrictions. There is no validation of it. 
When you has normal XHR code there is per default an validation of the same host.
Also any Virus detection tools can block it when they found a signature of malicious text (code).
This is not given in an image.

Before canvas, there was for my opinion no chance to get the byte data on any image values. So you can't deliver code in it.

The attack model here is with 3 lines of legal code and via image loading an attack is possible from single user to enterprise company’s.
Comment 7 Boris Zbarsky 2012-11-21 21:04:52 UTC
> When you has normal XHR code there is per default an validation of the same
> host.

Yes, but hosts can opt in to loads from them.

And while browsers can load images from anywhere, and draw them into a canvas, they can only getImageData the result if the image was from the same host or if the host opted into it, just like XHR.

> Also any Virus detection tools can block it when they found a signature of
> malicious text (code).

Again, if the web page is not cooperating, right?  If the web page and the server are cooperating, then they can just obfuscate the source code (rot13, encrypt, encode as an image, whatever).

It really would help if you answered my questions about your attack model... because as far as I can tell, getImageData doesn't allow anything XMLHttpRequest didn't already allow.
Comment 8 rcabanie 2012-11-22 04:35:02 UTC
(In reply to comment #7)
> > When you has normal XHR code there is per default an validation of the same
> > host.
> 
> Yes, but hosts can opt in to loads from them.
> 
> And while browsers can load images from anywhere, and draw them into a
> canvas, they can only getImageData the result if the image was from the same
> host or if the host opted into it, just like XHR.
> 
> > Also any Virus detection tools can block it when they found a signature of
> > malicious text (code).
> 
> Again, if the web page is not cooperating, right?  If the web page and the
> server are cooperating, then they can just obfuscate the source code (rot13,
> encrypt, encode as an image, whatever).
> 
> It really would help if you answered my questions about your attack model...
> because as far as I can tell, getImageData doesn't allow anything
> XMLHttpRequest didn't already allow.

I agree.
A script has multiple other ways to obfuscate malicious code.
This is an interesting way of new way of transmitting JS code, but it doesn't open up a new attack vector since it's easy to encrypt JS.
Comment 9 rcabanie 2012-11-22 04:35:38 UTC
EDITOR'S RESPONSE: 
This is an Editor's Response to your comment. If
you are satisfied with this response, please change the state of
this bug to CLOSED. If you have additional information and would
like the Editor to reconsider, please reopen this bug. If you would
like to escalate the issue to the full HTML Working Group, please
add the TrackerRequest keyword to this bug, and suggest title and
text for the Tracker Issue; or you may create a Tracker Issue
yourself, if you are able to do so. For more details, see this
document:
       http://dev.w3.org/html5/decision-policy/decision-policy.html