Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Canvas Fingerprinting: Cookies on Steroids

DZone's Guide to

Canvas Fingerprinting: Cookies on Steroids

In this article, we go over the basics of canvas fingerprinting, and how you how to use JavaScript to create your own canvas fingerprinting library.

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

Recently, the number of conversations about confidentiality and the ethics of tracking users has been growing rapidly, with the reselling of user's data to advertising agencies becoming an excellent way to monetize data. Google and Facebook bring in billions of dollars using data which you send to them for free. Everything that you do on the network will be used with one target - earning money off of you. Some people were discouraged by this fact and tried to eliminate companies like Google and Facebook from their Customer/Advertising chain using ICOs - but that's a completely different story.

Dear user, remember - if you use a product for free, YOU ARE THE PRODUCT when Facebook bought Instagram, Mark didn't pay for a unique idea and effective algorithms. No, he paid money for users, roughly $28 for each of Instagram’s users at the time.

But this article is not about morality or principles of freedom in the network, it's dedicated to one of the most prominent approaches that is widely used for tracking in the network. As you probably already guessed from the title, we're going to be talking about the canvas fingerprinting technique.

As this term may be known to everyone who reads this article, let me explain this approach step-by-step. When you are surfing the Internet, reading tweets, watching favorite vlogs on Youtube, or looking at photos on Instagram, you left your digital track. One of them are cookies, which is how websites store information about your preferences, like items in a cart on an e-commerce site; they are necessary for authentication on some sites, etc. But what if you want to track your potential customers on different sites with a unique id? This sounds like a hard task, but, in reality, it's not. Canvas fingerprinting solves this problem seamlessly.

Canvas fingerprinting is a technique for tracking online users that allow websites to identify and
track visitors using the HTML5 canvas element instead of browser cookies or other similar means. It's like a cookie on steroids. The main responsibility of canvas fingerprinting is collecting information about a remote computing device for the purpose of identification. Sites try to fetch as much as possible from your metadata like fonts, OS, and specific system properties and try to draw hidden 3D canvases which will be converted into a unique token for further identification on another site, advertising some goods on e-commerce sites or for recommendation system in the social network. 

Variations in the time it takes to render a 3D canvas allows for the generation of a unique token for each user. In fact, this approach was widely used for deanonymization of Tor's user. Tor's developers have since made a patch for this exploit, and now, Tor notifies users of canvas read attempts and returns blank image data.

How to Protect Yourself

A lot of add-ons allow you to prevent an attempt to fetch a canvas fingerprint, some of the most popular are Privacy Badger and Canvas Defender, and, as mentioned above, Tor browser protects users from it by default. Beginning October of 2017, Firefox prevented canvas fingerprinting by default, Firefox takes a bite out of the canvas while the other browsers don't prevent it.

Image title


Firefox prevents fetching canvas fingerprint.

Image title                      Docker hub attempted to fetch canvas fingerprints but was locked by the add-on.

Canvas Defender allows you to generate dummy noise, for obfuscation of your ID in the network. It's a pretty simple, but effective extension.

Image title

Dummy noise

Let's write our own library for fetching a canvas fingerprint.

We will use multiple sources for generating a unique token:

  • Canvas fingerprinting

  • Screen Resolution

  • Color Depth

  • Time Zone

  • UserAgent

  • Languages

  • CPU class

  • For storage, we can use:

    • Session storage

    • Local storage

    • Indexed DB

    • Open DB

    • IE AddBehaviour

    • IE-specific plugins like RealPlayer, AcroPDF, AgControl.AgControl - for Silverlight etc.

  • DNT header - as ironic as it may be. 

After collecting all the metadata in a single place, they are joined with MurmurHash. In the result, you have integer value which represents the fingerprint of your browser.

The function which draws a hidden canvas:

getCanvasFingerprint: function () {
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      var txt = 'CANVAS_FINGERPRINT';
      ctx.textBaseline = "top";
      ctx.font = "14px 'Arial'";
      ctx.textBaseline = "alphabetic";
      ctx.fillStyle = "#f60";
      ctx.fillRect(125,1,62,20);
      ctx.fillStyle = "#069";
      ctx.fillText(txt, 2, 15);
      ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
      ctx.fillText(txt, 4, 17);
      return canvas.toDataURL();
    }

Example of fetching some metadata that was fetched by a library - a full listing of the source code with all metadata from the list above can be found on my GitHub:

    getScreenResolution: function () {
        return (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height];
    },

    getRegularPluginsString: function () {
      return this.map(navigator.plugins, function (p) {
        var mimeTypes = this.map(p, function(mt){
          return [mt.type, mt.suffixes].join('~');
        }).join(',');
        return [p.name, p.description, mimeTypes].join('::');
      }, this).join(';');
    },

    hasSessionStorage: function () {
      try{
        return !!window.sessionStorage;
      } catch(e) {
        return true;
      }
    }

Library usage:

var fingerprint = new Fingerprint();
 document.getElementById('withCanvasDrawing').innerHTML = fingerprint.get();

Flag for drawing canvas to only fetch clients' metadata:

var withCanvasDrawing = new Fingerprint({canvas: true});
var withoutCanvasDrawing = new Fingerprint({canvas: false});

Using a custom hash function:

var withCanvasDrawing = new Fingerprint({hasher: pearson_hash});

That's all! You can find a full listing of the source code on my GitHub repository.

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
privacy ,security ,web security ,cookies

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}