Fun with Cross-Site Scripting (XSS)

May 4th, 2012 :: Web Development

I recently started seeing data in my Google Analytics from two pages that aren’t mine, which is something that usually happens when someone copies your HTML source code without paying much attention. The traffic data assumes that the root URL of all page hits is yours and therefore hides it, but searching for the relative path on Google quickly uncovered the perpetrator.

Guy Fawkes mask

To my surprise, it was the Turkish website of LG Electronics that was using my Google Analytics tracking code. On top of that, they were also hotlinking to one of my locally hosted copies of prefixfree.js, which I’m not even sure they’re getting any use of. One would think that a big company such as LG would have web developers that knew better.

So, seeing that they’re hotlinking to one of my script files, I decided to have some fun with cross-site scripting. To not get into any trouble, I figured I should stay away from trying to break the site, although there would have been lots of fun things that I could have done (like inserting and playing around with fool.js). But what if I could at least use the injected script to prevent the Google Analytics code from sending data to my account?

With that goal in mind, let’s look at some of the code that they copied:

<script type="text/javascript" src="http://joelb.me/scrollpath/script/lib/prefixfree.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25206568-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

At the top you’ll see the hotlinked script and below that is the Google Analytics code.

There are two things that are important to note here, the first is that the hotlinked script is included before the Google Analytics code. Secondly, look closer at line 3:

var _gaq = _gaq || [];

This line of code sets the _gaq variable to an empty array, but only if the variable has not already been defined. This means that we are free to define our own version of _gaq in the injected script, without it being overridden. The next two lines (4 and 5) use the push method to set the tracking options, so we need to have that defined on our object to avoid run-time errors.

There are probably a lot of things that can be done with the _gaq variable to prevent the rest of the code from sending any data to Google Analytics, but I decided to set up an object that replaces the UA-25206568-1 tracking code with UA-XXXXXXXX-X, by using the push method. By replacing the tracking code, the Google Analytics servers won’t be able to identify the account to send the data to, thus preventing the site from cluttering up my traffic data. Here’s the object with its push method:

_gaq = {
  push: function(value) {
    if (value[0] === "_setAccount" && value[1] === "UA-25206568-1") {
      _gaq = [["_setAccount", "UA-XXXXXXXX-X"]];
    } else {
      _gaq = [value];
    }
  }
};

When the push method of _gaq is used and the tracking code is set to mine, the method overrides the _gaq object to a regular array containing the replaced tracking code. I’ve also set a fallback in case they decide to change the code to something that doesn’t concern me.

The last thing I added was a message that gets printed out to the console when you visit the page, which you’ll be able to see until they remove the copied source code. It will be interesting to see how long it takes for them to notice this.

  • http://twitter.com/carlinscuderi Carlin Scuderi

    I was pretty surprised that all you did was calmly correct the error and print something to the console! I would’ve definitely gone full Mr. T. 

  • http://twitter.com/adamlapczynski Adam Lapczynski

    Very curious to see if they ever notice. Nicely done.

  • http://2bluesolutions.ca/ Brian B

    Fantastic. This really made my day.  Still chuckling.

  • Jparishdev

    Wonderful entry and a gentlemanly response to a very unscrupulous set of developers.

  • G_Mali

    This is funny. I would wait maximum for a week for any changes before emailing someone. Hotlinking isn’t cool.

  • PM

    What do you mean by searching for the relative path?

    • JoelBesada

      The page shows up as “/tr/cinema-screen/index.jsp” in Google Analytics, because it assumes you already know what the root URL is. So I had to use Google to find the complete URL, like this.

  • http://www.facebook.com/redhotbabe Sarah Cartwright

    The code’s in there, but it’s not appearing in my console…

  • gbrindisi

    LOL, maybe you should just have a look at BeEF: http://beefproject.com :)

  • jumplinkdesign

    you’re tolerant. I wouldnt care getting in trouble if that happened. Hey where’ s the link to your original site?

    • JoelBesada

      This blog is all I have at the moment. I might create a page on joelb.me (which right now just redirects here) in the future, if I find the time and inspiration to do so. 

  • http://www.patibs.nl/ Ebrahim Patel

    This is beyond belief Joel.

  • http://www.facebook.com/garbonzo Gary Reckard

    Classy! 

  • IrmaSDean
  • Loaderz1993

    “>alert(document.cookie)

  • http://twitter.com/geekz Murali Kumar

    lol. its still there!

  • http://twitter.com/mohit22dec1986 Mohit Zinzuvadia

     I can’t see any msg on the lg page..!! What’s the msg you have printed out…?? I can see that they are still using the same js link pointed to your site..!! Fools..!!

  • Jak

    How odd! Surprised at such a mature response (nothing against yourself) – had it’ve been most people, the site would not be up for much longer.

  • JimmyD

    Brilliant

  • http://twitter.com/jwandborg Joar Wandborg

    It’s still there to this day.

  • Pegpro

    Still nothing has been done to this day. Though I believe they’ve removed the analytic code

  • Darlito Bernard Delizo

    Looks like the console message that you added is still there, lazy bastards.

  • Jochem Nabuurs

    LOL… It’s still there…

  • Guest

    still there! 

  • murat

    As of today (20.03.2013) the message still appears in the console. What a shame for web developer(s) working for a big company.

  • SP

    Amazing. Still there, reading this article 11 months beyond post time. I guess such webdevs don’t use consoles looking at all the errors it spits out :)

  • http://www.nokes.de/ Nico

    omg man ….

  • http://exotikcar.com location voiture agadir

    Lol, the Message still there it take long time since May 4th, 2012 :p :

    ‘Hello there, this is a message from Joel Besada. (http://joelb.me)

    Please change or remove the Google Analytics code on this page.
    You have unprofessionally copied the source code (including my
    Google Analytics tracking code) from one of my pages, which is
    cluttering up my analytics with your traffic data.

    Also, hotlinking script files is bad.’,

    Bad bad LG webmasters.

  • mastrobardo

    ahaha thanks for the smile. Someone pls mail to LG to change the dev team!

  • moabi

    Still working !!! really unprofessional ^^

  • idarktech

    Omg! 2013 and it’s still there! =))

  • Godrifle

    Nice. Console message is still there.

  • Skewl84

    2 years and still going strong.. Kudos Joel and boo to the web developers of LG electronics..

  • maik

    still there :D

  • nagel

    And its still there to this day…

  • Peter Mouland

    checked today (mar, ’14) and i didn’t get to see the message :( I would have definitely done something more devastating, like hiding everything the users ‘hover’ over :)

  • https://github.com/xgqfrms/blogs xgqfrms

    Cross-Site Scripting (XSS)