Detecting Privacy Badger’s Canvas FP detection

栏目: IT技术 · 发布时间: 6年前

内容简介:Hello readers! As promised inprevious blog post, today I’ll write (a bit more technically) about third party JS security, but from a different angle.Privacy Badger

Hello readers! As promised inprevious blog post, today I’ll write (a bit more technically) about third party JS security, but from a different angle.

Privacy Badger

Privacy Badger is a privacy focused browser extension by EFF , that detects and blocks third party trackers. Unlike other extensions, it does it by analyzing the tracking behaviors, rather than relaying on domains blacklist.

Canvas fingerprinting

On of these tracking behaviors is canvas fingerprinting, which I briefly mentioned in previousblog posts. Generally speaking, canvas fingerprinting is a method to generate stateless, consistent, high entropy identifier from the HTML5 canvas element , by drawing several graphics primitives into it and then serialize its pixels. Different browsers and devices produce slightly different pixels due to differences in their graphics rendering stack. You can read the paper “ Pixel Perfect: Fingerprinting Canvas in HTML5 ” for more info.

Privacy Badger Canvas fingerprinting detection

From Privacy Badger website:

Does Privacy Badger prevent fingerprinting?

Browser fingerprinting is an extremely subtle and problematic method of tracking, which we  documented with the Panopticlick project . Privacy Badger 1.0 can detect  canvas based fingerprinting , and will block third party domains that use it. Detection of other forms of fingerprinting and protections against first-party fingerprinting are ongoing projects. Of course, once a domain is blocked by Privacy Badger, it will no longer be able to fingerprint you.

How Privacy Badger detect canvas fingerprinting

Privacy badger injects fingerprinting.js , along with several other context scripts, as specified in its manifest.json , to all the frames ( all_frames : true ) of all the pages ( “matches”: [ “<all_urls>” ] ) visited by the user, before any other script in the page has executed ( run_at : document_start ).

Content script have access to their frame DOM, but a separate JavaScript context. Because the goal of the script requires to monitors things that happen in the page JS context (canvas manipulation and serialization), this content script injects another, self removing script into the frame DOM, which executes in its JS context.

This script hooks into several canvas related APIs, including fillText (manipulation) and toDataURL (serialization). I wrote about JS hooking before, in the context of spoofing viewabiliy measurements . Whenever once of these APIs gets called, Privacy Badger hook is figuring out the caller script URL form within the call stack.

Threat Model

When designing and implementing fingerprinting countermeasures, there are two significant concerns:

  • Observability: which means trackers can fingerprint the presence of the fingerprinting countermeasure itself and using it as another data point in the fingerprint.
  • Bypassability: which means tracker can evade the fingerprinting countermeasure or rendering it useless, thus getting access to the desired fingerprinted feature.

Vulnerabilities in Privacy Badger canvas fingerprinting detection

  • Observability of the canvas API hooking:

as I wrote previously in depth at “ JavaScript tampering – detection and stealth ” (my most visited blog post so far!), there are several methods to detect that a native function was tampered with. Privacy Badger recognized this threat and tries to hide the tampering by setting the length, name, and toString properties of the hooked functions to match those of the original, but without referring to the native Function.protype.toString, a tracker can write:

Function.prototype.toString.call(HTMLCanvasElement.prototype.toDataURL);

And get:

"function wrapped() {
          var args = arguments;
...

Of course, it also won’t pass the prototype and hasOwnProperty test (detailed explanationhere).

  • Bypassability of the APIs hooking

Privacy Badger recognized this threat site code tampering with its own code, and tries to prevent this by copying the objects it uses into its own function scope . However, it still relies on prototype inherited methods inside the hook code itself, and these methods can be abused to steal the reference to the original API. Let’s look closely on the hook code itself , which gets called whenever a consumer calls one of the hooked canvas APIs:

function wrapped() {
          var args = arguments;

          if (is_canvas_write) {
            // to avoid false positives,
            // bail if the text being written is too short
            if (!args[0] || args[0].length < 5) {
              return orig.apply(this, args);
            }
          }

          var script_url = (
              V8_STACK_TRACE_API ?
                getOriginatingScriptUrl() :
                getOriginatingScriptUrlFirefox()
            ),
            msg = {
              obj: item.objName,
              prop: item.propName,
              scriptUrl: script_url
            };

          if (item.hasOwnProperty('extra')) {
            msg.extra = item.extra.apply(this, args);
          }

          send(msg);

          if (is_canvas_write) {
            // optimization: one canvas write is enough,
            // restore original write method
            // to this CanvasRenderingContext2D object instance
            this[item.propName] = orig;
          }

          return orig.apply(this, args);
        }

As we can see, there’s an interesting exception: if is_canvas_write is true and the length of the first arg is shorter then 5, the original function gets called, using the prototype inherited apply method , and returns before send(msg) is called, so Privacy Badger won’t be considering it as a fingerprinting attempt, to avoid false positives.

We can look few lines up and see that is_canvas_write  is computed as:

var is_canvas_write = (
        item.propName == 'fillText' || item.propName == 'strokeText'
      );

So, our attack will look like this:

    • Hook the apply method
    • Call the hooked fillText or strokeText
    • Steal the reference to the original fillText or strokeText
    • Write to the canvas text with length > 5 using  the original function

Let’s implement a PoC:

let _apply = Function.prototype.apply;
let original;
Function.prototype.apply = function () {
	// `this` is the function
	if (this.name === 'fillText' || this.name === 'strokeText') {
		original = this;
	}
	// restore the original apply
	Function.prototype.apply = _apply;
};

Then, we call the function:

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.fillText('a');
};

And now we have the original fillText:

original
ƒ fillText() { [native code] }

Viola!

The same technique can be used to extract the original serialization method, toDataURL. Notice the call to getOriginatingScriptUrl which is also using prototype inherited methods that can be tampered with.

Another bypass method is to obtain a references to the original APIs by using the iframe sandbox attribute . This attribute allows us to specify permissions for the content inside the iframe, and if we specify the allow-same-origin permission and don’t specify the allow-scripts  permission, the script injected by the context script won’t execute, according the the sandbox policy[1], but the embedding page will be able to access the iframe’s contentWindow and obtain an unhooked canvas from it.

That’s it for today! Although this topic could be expanded  even more, I’ll save something for next time

Hope you enjoyed, and feel free to contact me to discuss any of it!

[1] This is currently true in Firefox, but not in Chrome. In the past I observed the same behavior in Chrome, but from my test it seems like now DOM script that was added from content script will execute inside sandboxed iframes. I’m not sure if that’s intentional.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创投42章经

创投42章经

曲凯 / 中信出版集团 / 2018-10-20 / 58.00

《创投42章经》是拥有百万粉丝的微信公众号“42章经”的精选文章合集,全书共分为心法、内功、招式和江湖传奇四部分。 在心法部分,读者可以学到一些创业与投资的底层思维方式;在内功部分,读者可以了解到,投资人看待一家公司经营状况的标准;在招式部分,读者可以看到作者作为一名资深投资人和睿智的观察者,对过去几年主要的公司、模式以及风口的判断;最后的江湖传奇部分,作者通过一些故事,帮助读者更好地理解当......一起来看看 《创投42章经》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具