I discovered Ghostery in the summer of 2012, when I was researching web-tracking and specifically web-tracking done through web fingerprinting. Ghostery is a really cool browser extension which helped me identify the domains that popular web fingerprinters used to deliver their code and thus allowed me to isolate and study the fingerprinting code. You can read all about that in our paper titled: “Cookieless Monster: Exploring the Ecosystem of Web-based Device fingerprinting“.
Since then, I’ve installed Ghostery in all my browsers and use it to quickly find out which third-party trackers, each website uses. For those of you who don’t use Ghostery (you should definitely check it out after you finishing this post), Ghostery will match network requests and JavaScript/HTML filepaths with third-party-tracker blacklists and notify you when it gets a match. It also has the ability to block specific trackers, from running altogether.
For instance, on my page, securitee.org, I am using StatCounter, a third-party web-analytics framework which fits the definition of what someone would call a third-party tracker. Thus, if you visit my site with Ghostery installed, you will, by default, get a pretty purple box as follows:
Today, while searching for something completely different, I realized that the way this works is that Ghostery adds a div element (styled as purple box) in the DOM of the webpage. After a couple of seconds, Ghostery automatically deletes the purple box, so that it doesn’t annoy the user. So, just for a few seconds, the page’s DOM contains one of those:
What this means, is that there is a window of time in which the visited webpage has the ability to find out whether the current user is using Ghostery or not, and also to manipulate the contents of that purple box.
Why should I care?
There are many reasons why a dodgy site would want to be able to detect Ghostery and thus many reasons why you should care. For instance:
- Fingerprinting. Now, the site knows that you are one of the, say 700,000 users that use Chrome and have Ghostery installed. While this may seem like a lot, Chrome currently has more than 50% of the browser market. Thus, with such a simple trick, we are narrowing down from hundreds of millions to less than a million users. Combine this with other vectors (e.g. screen size, plugins, and fonts), and you are more unique than you would expect. If you don’t believe me, check out Panopticlick and then read our paper 🙂
- Misguiding. Some sites have a list of third-party trackers that almost matches the height of your screen. The ability to modify, or altogether hide, that tell-tale purple box can be very appealing to them. I want to be fair here and say that Ghostery is also using a dedicated box (shown when you click on the little Ghost next to the status bar) which cannot be touched by JavaScript running in the page.
- User Discrimination. If a company really, really, wants to track you, and they detect the presence of Ghostery, they may do all sorts of evil things. For instance, they could on purpose break the page so that you attribute the broken functionality to Ghostery rather than to the page itself.
Detection Methodology
There are probably many elegant ways to detect that Ghostery <div>. I, however, never claimed to be elegant :). What I did, is I wrote a small function that is called many times per second, which bruteforces all the possible identifiers of that div element. While this sounds like a lot, it isn’t. I noticed that all purple boxes have an id equal to “ghostery-alert-X” where X is an integer from 1 to 9999. Once the page starts, the function will keep on trying to find the ghostery <div>.
var tries = 0; var int_id = window.setInterval(function(){ for(var i=0; i < 10000; i++){ var cid = "ghostery-alert-" + i; var purple_box = document.getElementById(cid); //Ghostery installed if (purple_box != null){ //Do dodgy things window.clearInterval(int_id); } else if(tries >= 1000){ window.clearInterval(int_id); } } tries += 1; },10);
Since I’m running this code every 10 milliseconds, I am also purposefully deleting the function after 1000 tries (should be about 10 seconds) so that it doesn’t keep on polling the user’s browser for ever.
If there is a purple box, this script will find it. As I mentioned earlier, you can do all sorts of things once you find it. Since I am not an evil guy, I decided to just make my mark and leave it at that:
Interestingly, in Firefox, the div has a static id equal to “ghostery-purple-bubble” which makes the whole thing trivial (and me kind of sad…).
What can be done?
If Ghostery decides that, that purple box is a must, then it will need to be recreated using a background page of a Chrome extension instead. Sure, it won’t be floating as nicely on the page, but it wouldn’t be detectable (at least in this way) from an “inquiring” page. As a matter of fact, Ghostery already has such a page which appears when you click on the little blue ghost (giving you many more details for each tracker), so maybe the purple box should go, altogether. I cannot predict whether tracking companies will pick this up, but if you want to make sure you can, for now, manually disable that purple box.
Conclusion
I want to repeat, once again, that Ghostery is an awesome tool (I use it daily and I will keep on using it) and thus this post is not meant to be a criticism towards it. I am merely pointing out how minor choices done in a browser context (e.g., “Wouldn’t it be nice to add a small floating box?“) can have later repercussions that may negatively affect a user’s privacy.
Till next time
Nick Nikiforakis
Great post. I also really enjoyed your bitsquatting paper BTW.
Thanks Jaeson 🙂 I appreciate the positive feedback
Pingback: Detecting Ghostery | The Good, The Bad and the ...
OK, I do like to be elegant, so let me try it for you ;-D
window.addEventListener("DOMSubtreeModified", function(e) {
if (e.target.id.search(/^(ghostery-alert-[0-9]+|ghostery-purple-bubble)$/) == 0)
e.target.innerHTML = 'All your bubbles are belong to us';
}, false);
I haven’t tested it in Firefox, only in Chrome.
Also note that, although Ghostery is also available for Opera, my script won’t work there since Opera doesn’t implement DOMSubtreeModified event.
Aahh, WordPress didn’t kept my indentation so my code was not as elegant as I intended 🙁
Indentation or not, this is elegant code 😉
Thanks.
I think that now will appear indented (hey, WordPress, what about a Preview button for comments?):
window.addEventListener("DOMSubtreeModified", function(e) {
if (e.target.id.search(/^(ghostery-alert-[0-9]+|ghostery-purple-bubble)$/) == 0)
e.target.innerHTML = 'All your bubbles are belong to us';
}, false);
Nice, I also think about regular expression when I read the post.
*disables purple box*
The point is not only using regular expressions, but mainly also using DOMSubtreeModified event so the function is only executed when a new DOM element is inserted instead of checking every 10 seconds.
Just go to the gosthery plugin configuration, then Advanced/ Display options and uncheck “show alert bubble”. The purple bubble is gone.
There is a much simpler malicious way to cover up the list of trackers. If the Ghostery popup didn’t happen to be visible on the page, I suspect the majority of people would assume that this means it didn’t detect anything at all. As such, you could simply have 10k CSS rules – one for each permutation of the ID – to simply set “display: none;” on it. I noticed from your screenshot that the display style isn’t one of the ones set, so this would then simply make the purple box not get rendered…
“If Ghostery decides that, that purple box is a must, then it will need to be recreated using a background page of a Chrome extension instead. ”
I don’t really know anything about this, but would that work on other browsers then? You only talk about Chrome, but the way Ghostery works now seems to make it pretty compatible and available on many other browsers as well.
Stereoled,
In the blog-post, I mentioned that this will work also in Firefox. I just focused more on Chrome, simply because that was the browser I was using, when I stumbled upon this issue.
Nick
Hi Nick,
Ghostery developer here.
Any extension that modifies pages is vulnerable to detection. We can make detection harder, but we can’t eliminate it, not without disabling Ghostery’s blocking capabilities. For example, a page could see if certain commonly-blocked elements are no longer present.
As far as I know, there is no way to have a per-tab purple alert bubble that behaves the way ours does now without injecting Ghostery code into the page. Since eliminating the bubble will not eliminate the possibility of detection, the bubble will likely stay. We plan on making the alert bubble harder to detect in the future.
Hi Alexei,
Thank you for taking the time to respond.
You are right about the blocking thing… a page can check whether the JavaScript objects that should be in the page, are in the page, and if they are not, conclude that something has blocked them (e.g. AdBlock Plus).
This issue however, allows a page to detect the passive presence of Ghostery, i.e., when Ghostery is simply naming the third-parties without any further actions.
As for the presence or absence of the bubble, at the end of the day, you guys are the ones making the choices 🙂
Best regards
Nick
I know that Ghostery allows you to disable the notification box. Does disabling it also remove the div insertion?
No real need for brute force:
document.querySelectorAll("[id*='ghostery-alert-']");
I’m presuming that for Chrome, the numeric portion of the 1-9999 is cached off so that the purple box div can be removed at a later time. In this case, randomly generate instead a GUID, check to make sure the page doesn’t already contain that value (a one in a billion-plus chance, maybe you can skip this check), and make a div that contains _only_ the GUID without any reference to its purpose? Maybe this could eventually become the standard ecosystem for 3rd-party web-page insertions (although then maybe malicious web pages could simply block all GUID-looking DIVs or other HTML elements… Oh, well, back to the drawing board…)
Ghostery is awesome! The best! My firefox speed has jumped since installing it.
Set it to block cookies and everything ,but social plugins because its how i leave comments