Security implications of WebRTC (part 3): Tracking users across domains
Identifying users on a website
There has been a lot of noise about WebRTC leaking IP addresses (e.g. for de-anonymizing users behind TOR or VPNs) in the past months. The IP addresses of internal interfaces might also be used to aid in browser fingerprinting.
Today, while working on our new AhoyRTC media engine, something different caught my eye. In the past, Google Chrome used to generate a new self-signed certificate for every WebRTC PeerConnection. But now (using Chrome 46, or maybe earlier as i did not check) it generates a self-signed certificate which is valid for one month and uses it for all PeerConnections of a particular domain.
This turns the fingerprint of the certificate into a unique tracking ID for a single user (at least for up to one month). The certificate fingerprint can be accessed from JavaScript by using the PeerConnection statistics api functions, it is not required to set up a full peer-to-peer connection (e.g. no packets will hit the network). No indication is given to the user.
// create a PeerConnection without using a STUN server var pc = new webkitRTCPeerConnection(null); pc.createOffer( function createOfferSuccess(description) { pc.setLocalDescription( description, function setLocalDescriptionSuccess() { // it takes a moment until the fingerprint shows up in the statistics setTimeout(function() { pc.getStats(function(stats) { var items = stats.result(); items.forEach(function(item) { if (item.type === "googCertificate") { console.log("Your fingerprint is " + item.id); } }); }); }, 500); }, function setLocalDescriptionError(error) { } ); }, function createOfferError(error) { }, { offerToReceiveAudio: true } );
To test this go to http://www.kapejod.org/tracking/fingerprint.html and to http://kapejod.org/tracking/fingerprint.html
Each of the two links shows a different fingerprint, because they are on different domains (www.kapejod.org and kapejod.org). Closing the tab, restarting Chrome or even rebooting the computer does not change the fingerprints.
How to track users across multiple domains?
This is pretty straight forward! Let your tracking code insert an iframe into every website you want to track. The iframe will always be loaded from one domain (in my example “kapejod.org” without “www”), resulting in one stable fingerprint.
The only challenge is to extract the fingerprint from the iframe. The browser’s cross origin policy prevents your website from accessing the iframe and also prevents the iframe from accessing the website it is embedded in.
But the point of the cross origin policy is not to prevent leaking information. When inserting the iframe into the website we can pass a (sort of random) unique identifier (a transaction id) to the iframe (as part of the url). Both the website and the iframe will use the same transaction id to load a tracking pixel from a remote server. This way the remote server can combine the information coming from two separate requests.
To test this go to http://www.kapejod.org/tracking/test.html and to http://kapejod.org/tracking/test.html. Open the network tab of Chrome’s developer console and compare the urls of the requested “tracking.png”. They should contain the same fingerprint, now!
www.kapejod.org: FE:24:D9:41:F6:AF:31:72:58:DA:08:F2:55:FC:45:A5:0B:D4:C4:E1:C7:F5:27:0E:3B:DF:F4:3C:88:F9:0D:88
kapejod.org: FE:24:D9:41:F6:AF:31:72:58:DA:08:F2:55:FC:45:A5:0B:D4:C4:E1:C7:F5:27:0E:3B:DF:F4:3C:88:F9:0D:88
What used to be two different fingerprints are now one! To make sure that I am not cheating please check for cookies…
The good news and the bad news
Actually the good news is pretty bad, too. The incognito mode of Chrome does not persist the certificates. But to make it generate a new one you have to close ALL incognito tabs. Otherwise you can be tracked across multiple domains.
The bad new is that in normal browsing mode, only clearing your browser data will reset the certificates. Doing that when going to a different website every time is a bit tedious…
Update
Because Google Chrome still supports SRTP key exchange via SDES (to be backwards compatible) it is even possible to retrieve the unique fingerprint without needing a remote server. The website and the iframe, it has inserted, can establish a bidirectional communication using the WebRTC data channel. This works although the iframe cannot send its SDP answer back to the website (but the website can derive the SDP answer from its own SDP offer).
To test it go to http://www.kapejod.org/tracking/track.html and to http://kapejod.org/tracking/track.html. Both pages will show a JS alert with the same fingerprint. If you are still not convinced you can include the following into any other website:
<script src="https://kapejod.org/tracking/usertrack.js"></script>