Detecting Ghostery

ghostery_logo

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:

Ghostery's purple box

Ghostery’s purple box

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:

ghostery_post_2

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:

Hijacking the purple box

Hijacking the purple box

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

This entry was posted in Breaking stuff. Bookmark the permalink.

18 Responses to Detecting Ghostery

  1. Great post. I also really enjoyed your bitsquatting paper BTW.

  2. Pingback: Detecting Ghostery | The Good, The Bad and the ...

  3. Chuso Pérez says:

    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.

    • Chuso Pérez says:

      Aahh, WordPress didn’t kept my indentation so my code was not as elegant as I intended :-(

      • nikifor says:

        Indentation or not, this is elegant code ;)

        • Chuso Pérez says:

          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);

    • JIghtuse says:

      Nice, I also think about regular expression when I read the post.
      *disables purple box*

      • Chuso Pérez says:

        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.

  4. Just go to the gosthery plugin configuration, then Advanced/ Display options and uncheck “show alert bubble”. The purple bubble is gone.

  5. Graham Cox says:

    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…

  6. stereoled says:

    “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.

    • nikifor says:

      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

  7. Alexei says:

    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.

    • nikifor says:

      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

  8. Misleadingrhino says:

    I know that Ghostery allows you to disable the notification box. Does disabling it also remove the div insertion?

  9. Profligate Penguin says:

    No real need for brute force:


    document.querySelectorAll("[id*='ghostery-alert-']");

  10. Daniel says:

    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…)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>