20

I manage a secured PHP/MySQL web app with extensive jQuery use. Today, a strange error popped up in our app's logs:

JS Error: Error loading script:
https://d15gt9gwxw5wu0.cloudfront.net/js/_MY_WEB_APP_DOMAIN_/r.js

We are not using Amazon's Cloudfront CDN in our app. When I go to the URL that failed to load, these are the only contents:

if(typeof _GPL.ri=='function'&&!_GPL.isIE6){_GPL.ri('_GPL_r')}_GPL.rl=true;

The user's user agent string is:

Mozilla/5.0 (Windows NT 6.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1

Please note: I am not the user who triggered this error. It was one of our thousands of users who triggered it. I do not have control over the client machine.

Does anyone know what's going on here? Is this some sort of XSS attack?

** Update **

It appears I'm not the only one who has discovered this anomaly on their website. I found this report of the same exact behavior, which seems to indicate the code is harmless, but still no answers as to where it came from.

In addition, I found this pastebin with similar code, that appears to be some sort of advertising script. Again, not terribly helpful.

** Update 2 **

More context: The webapp uses several third party jQuery plugins but no third party analytics of any kind. All scripts are hosted on our own server, and an audit of all our code provides no matches for "cloudfront".

This app has been in production for about 4 years, and this is the first and only instance of any activity like this. It has not happened before or since, so I doubt I'll be able to reproduce it.

What I'm interested in is if this is some sort of attack. If it is, I want to know how to plug the hole it's trying to exploit if it's not plugged already.

Andrew Ensley
  • 11,611
  • 16
  • 61
  • 73
  • Do you have any statistics included in the page, like e.g. Google Analytics? Or any other third party script? Do you have some add-on installed in firefox? – Gerben Feb 10 '12 at 20:15
  • We're not using any third party Analytics, but we are using some third-party jQuery plugins. An audit of all our code provides no matches for "cloudfront". – Andrew Ensley Feb 10 '12 at 20:39
  • jQuery and the plugins that you're using - are they hosted locally, at your server, or are you loading them externaly, e.g. from Google's libraries repository? – avramov Feb 10 '12 at 21:53
  • What happens if you remove those scripts? – Gerben Feb 10 '12 at 22:10
  • Been looking into this myself the past few days... For me, it appears that it is a BHO/Plug-in that is prepending code on a specific users input... Part of the time as a hidden iframe and part of the time as a script tag... Looking into the cloudfront scripts it appears the iframe loads d.textsrv.com and the embeded script loads ads2srv.com.. When you view source, what is the script associated with? (A post?) – CarpeNoctumDC Feb 11 '12 at 03:13
  • @egasimus: all of the scripts are hosted on our server. – Andrew Ensley Feb 11 '12 at 03:47
  • @Gerben: this is a production web-app, I can't just remove scripts and test. Also, it has been in production for over 2 years, and so far we only have one documented case of this happening. I'm not even sure I could reproduce this scenario ever. As I mentioned, I suspect it's an XSS attack with an obviously unknown source. – Andrew Ensley Feb 11 '12 at 03:48
  • @CarpeNoctumDC: I have posted the entire source of the script that resides on cloudfront in my question. It is only that single line. – Andrew Ensley Feb 11 '12 at 03:48
  • @Andrew have you found the root cause of the script? e.g. where it is being loaded? In the instance I have been looking into it is being inserted/prepended to a users post (composed in fckeditor)... When someone else views that post it either has an iframe or script tag prepended. – CarpeNoctumDC Feb 11 '12 at 16:51
  • Based on the answer below, could you check if the additional script is loaded when you view the site from several different computers? It sounds like something like Yontoo Layers might be responsible. (Would show up in _Add/Remove Programs_.) – Jordan Gray Feb 11 '12 at 19:18
  • @JordanGray: this didn't happen on my machine. It was one of the thousands of users on our production webapp. I don't have control over the client machine. – Andrew Ensley Feb 11 '12 at 22:57
  • @Andrew, based on this, I strongly suspect that this is nothing to do with your webapp; rather, it is a script being injected by a plugin on the client's machine. Yontoo Layers is an example; users often do not install it intentionally, and I believe it does inject script directly into pages (as per Steffan's analysis). – Jordan Gray Feb 14 '12 at 14:22
  • Note for future generations: I had a similar problem with strange 3rd party js code causing errors, and it turned out to be a (semi-)malicious browser toolbar injecting code into web pages. I ended up writing a detector script and showing a warning to users. – Joel L Dec 03 '12 at 16:14
  • @JoelL Good point. I ended up doing the same thing. This is my solution for those interested: http://stackoverflow.com/questions/10218132/javascript-detect-prevent-external-scripts/10453353#10453353 – Andrew Ensley Dec 03 '12 at 17:57

2 Answers2

33

Disclaimer: I'm not a security analyst/expert, your issue simply sparked my interest ;)

Warning: While I share the initial conclusion that the code itself is probably harmless, the underlying technology can most certainly be (ab)used for malicious intents as well, so please take care when investigating this yourself.

Analysis

You already found the relevant evidence yourself - searching further I found another pastebin drop, which is more readable, so I'm using this for the explanation (though at first sight the other one would allow this as well after formatting).

The snippet features JavaScript fragments with the following major functionality:

  • Line 13 initializes the variable _GPL with all sorts of items for later use, e.g. various constants`, helper functions, browser compatibility stuff and actual payloads, for example:

    • Line20 defines an empty basdeCDN, line 21 defines a fCDN, which happens to be the one in question (d15gt9gwxw5wu0.cloudfront.net)

    • line 261 defines a function removeScripts(), which in turn uses findScript()from line 266, further accompanied by insertJS() on line 277 - their respective intend is obvious

    • line 270 defines function loadDomainRules(), which seems to be the one generating the URL you have found in your logs - see appendix below for the code snippet

      • Deduction: Even without further evidence gathered below, the naming and functionality strongly hints on r.js being a JavaScript file serving custom JavaScript specifically assembled/generated for the domain at hand

    • line 100 defines a function loadGeo(), which references some kind of an ad server indeed (ads2srv.com) - see appendix below for the code snippet

    • line 368 finally defines a function i(), which provides the most definite clues regarding the likely origin of all this, namely the notion of some Yontoo Client and Yontoo API - see appendix below for the code snippet

Corollary

What's it all about?

The extracted clues Yontoo Client and Yontoo API easily lead to Yontoo, an Application Platform that allows you to control the websites you visit everyday, i.e. it sounds like a commercialized version of Userscripts.org, see What is a Yontoo App?:

Yontoo is a browser add-on that customizes and enhances the underlying website

Where Can I Use It?

Yontoo works on any site on the Web, although the functionality comes from separate applications called Yontoo Apps which provide specific functionalities depending on what site you are on.

[emphasis mine]

Now, looking at the current listings in their App Market easily demonstrates, why this might be used for questionable nontransparent advertizing as well for example, all the trust signs and seals in their footer notwithstanding.

How did it end up in your logs?

Another quote provides more insight into the functionality and how it might have yielded the issue you've encountered:

Yontoo [...] is a browser add- on that creates virtual layers that can be edited to create the appearance of having made changes to the underlying website. [...] If you see a need for an application or tool over a website, then you are free to create!

So somebody apparently has visited your site and created some custom domain rules for it by means of the Yontoo client (if it actually allows this for end users) or one of the available apps (the snippet used for analysis references the Drop Down Deals app in line 379 for example), which triggered the creation of d15gt9gwxw5wu0.cloudfront.net/js/_MY_WEB_APP_DOMAIN_/r.js to store these rules for reuse on next site visit in turn.

Due to some security flaw somewhere (see conclusion below) this URL or a respective JavaScript snippet must have been injected into JavaScript code of your application (e.g. by means of Cross-site scripting (XSS) indeed), and triggered the log entry error at some point in turn.

Conclusion

As mentioned upfront already, I share the initial conclusion that the code itself is probably harmless, although the underlying technology can most certainly be (ab)used for malicious intents as well due to its very nature of mocking with client side JavaScript, i.e. a user allows code from a 3rd party service to interact with sites (and especially data) he uses and trusts every day - your case is the apparent evidence for something gone wrong already in this regard.

I haven't investigated the security architecture (if any) of Yontoo, but wasn't able to find any information regarding this important topic immediately on their website either (e.g. in their Support section), which is pretty much unacceptable for a technology like this IMHO, all the trust signs and seals in their footer notwithstanding.

On the other hand, users do install 3rd party scripts from e.g. Userscripts.org all the time of course, not the least for fine tuning the user experience on Stack Exchange as well ;)

Please make your own judgment accordingly!


Appendix

Below you can find the code snippets referenced in the analysis (I've been unable to inline them within the lists without breaking the layout or syntax highlighting):

loadDomainRules()

function () {
    if (location.host != "") {
        var a = location.host.replace(RegExp(/^www\./i), "");
        this.insertJS(this.proto + this.fCDN + "/js/" + a + "/r.js")
    }
    this.loaded_domain_rules = true
}

loadGeo()

function () {
    var cid = this.items.e6a00.get("geo.cid");
    var updatetime = this.items.e6a00.get("geo.updatetime");
    if (!cid || (cid && updatetime && (Math.floor((new Date()).getTime() / 1000) - parseInt(updatetime)) >= 259200)) {
        this.insertJS(((this.proto == 'https://') ? 'https://s.' : 'http://') + 'ads2srv.com/tb/gc.php?json&cb=_GPL.setGeoAndGo')
    } else {
        this.vars.cid = this.items.e6a00.get("geo.cid");
        this.vars.rid = this.items.e6a00.get("geo.rid");
        this.vars.ccid = this.items.e6a00.get("geo.ccid");
        this.vars.ip = this.items.e6a00.get("geo.ip");
        this.loadCC();
        this.loadDomainRules()
    }
}

i()

function () {
    if (typeof YontooClient != 'undefined') YontooClient = {};
    if (typeof yontooAPI != 'undefined') yontooAPI = {};
    if (typeof DealPlyConfig != 'undefined') {
        DealPlyConfig.getBaseUrl = function () {
            return "https://d3lvr7yuk4uaui.cloudfront.net/items/blank.js?"
        };
        DealPlyConfig.getCrownUrl = function () {
            return "https://d3lvr7yuk4uaui.cloudfront.net/items/blank.js?"
        }
    }
    this.rm(this.ri, ['dropdowndeals', 'Y2LeftFixedCurtain', 'gbdho', 'bdca', 'dealply-toast-1', 'pricegong_offers_iframe', 'SF_VISUAL_SEARCH', 'batAdRight', 'batAdBottom', 'batAdMiddle_0', 'batAdMiddleExt1_0', 'batAdRight2', 'invisiblehand-iframe', 'scTopOfPageRefinementLinks', 'sf_coupon_obj']);
    this.rm(this.rc, ['yontoolayerwidget', 'dealply-toast', 'imb-ad']);
    this.rm(this.ric, [
            ['productbox', 'g'],
            ['related-searches', 'related-searches-bing']
        ]);
    this.rm(this.rtn, ['MIVA_AdLink', 'itxtrst', 'kLink', 'FAAdLink', 'IL_AD', 'skimwords-link'])
}
Community
  • 1
  • 1
Steffen Opel
  • 63,899
  • 11
  • 192
  • 211
  • 2
    Excellent analysis. Thank you for your help in figuring this out. – Andrew Ensley Feb 14 '12 at 22:50
  • Great answer from Steffen. Just to add - I was noticing this in my Net logs as well and it stopped when I disabled an extension called Widgi Toolbar. I don't recall adding this extension and I don't use Firefox to browse the Internet, so I am suspect as to what it may have come packaged with that I currently use. – Christian Duvall Feb 27 '12 at 13:18
  • The analysis is perfect, what would you say anout the same line on AkamaiHD with exatly the same line? http://cdncache-a.akamaihd.net/js/d6f636e256e696c6e6f6d287967616d6/r.js – Ruslan Abuzant Jul 26 '13 at 17:53
  • I have experienced something similar; in that I am logging client side errors, and I have thousands of errors relating to javascript files that have nothing to do with my site, but they do mention YontooClient. The errors are logged on pages where I observe no opportunity for script injection. So my conclusion is these are caused by some kind of browser plugin rather than a security flaw in my site. So I am inclined to define these as "self-inflicted-XSS", Does that make sense? – Myster Jun 02 '15 at 00:12
0

I found an iFrame as well in my drupal 7 website. It was loaded into the site by enabling the module of sharaholic.

Bjorn
  • 1