New issue
Advanced search Search tips

Issue 906412 link

Starred by 2 users

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows , Chrome , Mac
Pri: 2
Type: Bug



Sign in to add a comment

Canvas crossorigin policy still enforced despite Access-Control-Allow-Origin

Reported by victorqr...@gmail.com, Nov 18

Issue description

This template is ONLY for reporting security bugs. If you are reporting a
Download Protection Bypass bug, please use the "Security - Download
Protection" template. For all other reports, please use a different
template.

Please READ THIS FAQ before filing a bug: https://chromium.googlesource.com
/chromium/src/+/master/docs/security/faq.md

Please see the following link for instructions on filing security bugs:
https://www.chromium.org/Home/chromium-security/reporting-security-bugs

Reports may be eligible for reward payments under the Chrome VRP:
http://g.co/ChromeBugRewards

NOTE: Security bugs are normally made public once a fix has been widely
deployed.

-------------------------

VULNERABILITY DETAILS
Chrome won't allow you to getImageData of an image that isn't yours, but, converting the image to base64 first, bypass that.

VERSION
Chrome Version: Version 70.0.3538.102 (Official Build) (64-bit)
Operating System: Debian GNU/Linux 9 (stretch)

REPRODUCTION CASE

https://github.com/victorqribeiro/scrap/blob/master/search.js

```
	let imgToFind = 'https://scontent.fpoa16-1.fna.fbcdn.net/v/t1.0-9/20292628_1441846932571303_2480010471403410393_n.jpg?_nc_cat=103&_nc_ht=scontent.fpoa16-1.fna&oh=6e082d65d0068a635624e3618b378d58&oe=5C6697C1';
	let toDataUrl = function(url, callback) {
		let xhr = new XMLHttpRequest();
		xhr.onload = function() {
		  var reader = new FileReader();
		  reader.onloadend = function() {
		    callback(reader.result);
		  }
		  reader.readAsDataURL(xhr.response);
		};
		xhr.open('GET', url);
		xhr.responseType = 'blob';
		xhr.send();
	};
	let looked = {};
	let t = 1;
	let cPos = 0;
	let mPos = document.body.offsetHeight;
	let canvas = document.createElement('canvas');
	canvas.width = canvas.height = 100;
	let c = canvas.getContext('2d',{alpha: false});
	let imgdata;
	let possible = [];
	let searchImg = new Image();
	toDataUrl(imgToFind,(r)=>{ 
		searchImg.src = r;
	});

```

FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: [tab, browser, etc.]
Crash State: [see link above: stack trace *with symbols*, registers,
exception record]
Client ID (if relevant): [see link above]

CREDIT INFORMATION
Externally reported security bugs may appear in Chrome release notes. If
this bug is included, how would you like to be credited?
Reporter credit: Victor Ribeiro

 
The README in that repo recommends opening the console and pasting in the code. This means that you aren't requesting a cross-origin image, since the code is running in a same-origin context. Is your PoC setup differently from the github repo?
Cc: drubery@chromium.org
When I first wrote the script, I tried to get the image data the usual way:

imgToFind = 'https://scontent.fpoa16-1.fna.fbcdn.net/v/t1.0-9/20292628_1441846932571303_2480010471403410393_n.jpg?_nc_cat=103&_nc_ht=scontent.fpoa16-1.fna&oh=6e082d65d0068a635624e3618b378d58&oe=5C6697C1';

It tainted the canvas, so I couldn't use the getImageData() function.

After that I implemented a base64 converter (like in the script, on repo) and draw the image as a base64.


let imgToFind = 'https://scontent.fpoa16-1.fna.fbcdn.net/v/t1.0-9/20292628_1441846932571303_2480010471403410393_n.jpg?_nc_cat=103&_nc_ht=scontent.fpoa16-1.fna&oh=6e082d65d0068a635624e3618b378d58&oe=5C6697C1';

	let toDataUrl = function(url, callback) {
		let xhr = new XMLHttpRequest();
		xhr.onload = function() {
		  var reader = new FileReader();
		  reader.onloadend = function() {
		    callback(reader.result);
		  }
		  reader.readAsDataURL(xhr.response);
		};
		xhr.open('GET', url);
		xhr.responseType = 'blob';
		xhr.send();
	};

        let searchImg = new Image();

	toDataUrl(imgToFind,(r)=>{ 
		searchImg.src = r;
	});

then it worked!
I meant to say:

let searchImg = new Image();

searchImg.src = 'https://scontent.fpoa16-1.fna.fbcdn.net/v/t1.0-9/20292628_1441846932571303_2480010471403410393_n.jpg?_nc_cat=103&_nc_ht=scontent.fpoa16-1.fna&oh=6e082d65d0068a635624e3618b378d58&oe=5C6697C1';

c.drawImage(searchImg,0,0);

this tainted the canvas;

the code on the message before bypassed that.
Showing with an screen shot.
Screenshot_2018-11-19_17-36-22.png
92.8 KB View Download
Cc: fs...@chromium.org
Components: Blink>Canvas
Labels: Security_Severity-Low Security_Impact-Stable OS-Chrome OS-Linux OS-Mac OS-Windows Pri-2
Status: Available (was: Unconfirmed)
Thank you for the additional info, I've managed to create a self-contained PoC from it. The issue can be reproduced by running `python cors_server.py`, then navigating the browser to http://localhost:8000/test.html

Clicking the first div (the first try may succeed, click again) will give an error message in the console due to the cross-origin taint. Clicking the second will succeeds every time. 

This bug seems to be that images with "Access-Control-Allow-Origin: *" still taint canvases, so the XHR succeeds, but the getImageData does not. Marking as low severity since getImageData is being more restrictive than necessary. 

+fserb@ for triage.
b906412.zip
10.6 KB Download
Is this eligible for a bounty?
By the way, what is a PoC?
Labels: -Type-Bug-Security -OS-Linux -Restrict-View-SecurityTeam -Security_Severity-Low -Security_Impact-Stable Type-Bug
Summary: Canvas crossorigin policy still enforced despite Access-Control-Allow-Origin (was: Security: bypass canvas crossorigin policy by converting the image to base64)
Per C6, this can be treated as a functional issue rather than a security one, in that access *isn't* being granted to a resource to which one *is* entitled (via Access-Control-Allow-Origin: *) rather than the other way around.

Removing restrictions.

Unfortunately, this is unlikely to be eligible for a bounty since it doesn't allow an adversary to obtain information to which they are not already entitled, because of the prerequisite of the  ccess-Control-Allow-Origin header. If you can show a case where you can obtain the same information in the absence of the Access-Control-Allow-Origin header, then we would reconsider the issue.

Sign in to add a comment