简体   繁体   中英

Javascript: Detect/Prevent External Scripts

Is it possible to detect external scripts that might be loaded into a page by browser add-ons, a proxy, xss, etc?

Say I have this web page:

<html>
    <head>
        <title>Hello world!</title>
        <script src="http://mydomain.com/script.js"></script>
    </head>
    <body>
        Hello world!
    </body>
</html>

Would it be possible to include some script in my script.js file that would detect when other script elements on the page do not originate from http://mydomain.com ?

I want something that could detect other scripts somehow included in the source (ie they are present when the onload event fires) and scripts added any time after page load .

If I can detect those scripts, can I also stop them somehow?

This would be useful in debugging javascript/ui issues reported by users if I knew there was other stuff going on.

I use jQuery, so a jQuery answer will work for me. I just didn't want to limit answers to jQuery only.


EDIT

My solution is below. However, there are two (potential) problems with it:

  1. It depends on jQuery.
  2. It will not detect foreign resources loaded via CSS @import rules (or any rule with a url() value).

If someone would like to submit an answer that solves one or both of those issues, I will upvote it.

If you solve both, I will accept your answer.

You could check all script elements on domready like this:

$(function () {
    $('script').each(function () {
        check script source here
    })
})

but, if someone could inject script tags in your side, he can also delete your code before you can start the check, also it will be hard to delete objects and functions the script could create before your recognize it.

So I dont think its a good solution to start investing time in this field. Its much more important to be clear that you cant trust the client anyway.

As you wanna figure out it anyway there are a bunch of DOM events to check if the DOM tree has changed.

I wasn't satisfied with the answers I received (though I appreciate Andreas Köberle's advice ), so I decided to tackle this myself.

I wrote a function that could be run on demand and identify any html elements with foreign sources. This way, I can run this whenever reporting a javascript error to get more information about the environment.

Code

Depends on jQuery (sorry, element selection was just so much easier) and parseUri() (copied at the bottom of this answer)

/**
 * Identifies elements with `src` or `href` attributes with a URI pointing to
 * a hostname other than the given hostname. Defaults to the current hostname.
 * Excludes <a> links.
 * 
 * @param string myHostname The hostname of allowed resources.
 * @return array An array of `ELEMENT: src` strings for external resources.
 */
function getExternalSources(myHostname)
{
    var s, r = new Array();
    if(typeof myHostname == 'undefined')
    {
        myHostname = location.hostname;
    }
    $('[src], [href]:not(a)').each(function(){
        s = (typeof this.src == 'undefined' ? this.href : this.src);
        if(parseUri(s).hostname.search(myHostname) == -1)
        {
            r.push(this.tagName.toUpperCase() + ': ' + s);
        }
    });
    return r;
}

Usage

var s = getExternalSources('mydomain.com');
for(var i = 0; i < s.length; i++)
{
    console.log(s[i]);
}

// Can also do the following, defaults to hostname of the window:
var s = getExternalSources();

The search is inclusive of subdomains, so elements with sources of www.mydomain.com or img.mydomain.com would be allowed in the above example.

Note that this will not pick up on foreign sources in CSS @import rules (or any CSS rule with a url() for that matter). If anyone would like to contribute code that can do that, I will upvote and accept your answer.


Below is the code for parseUri() , which I obtained from https://gist.github.com/1847816 (and slightly modified).

(function(w, d){
    var a,
        k = 'protocol hostname host pathname port search hash href'.split(' ');
    w.parseUri = function(url){
        a || (a = d.createElement('a'));
        a.href = url;
        for (var r = {}, i = 0; i<8; i++)
        {
            r[k[i]] = a[k[i]];
        }
        r.toString = function(){return a.href;};
        r.requestUri = r.pathname + r.search;
        return r;
    };
})(window, document);

You could listen for changes in DOM and see if a new script tag is being inserted. But may I ask, what is the reason for such a need? I doubt you will be able to detect all possible cases where some arbitrary JS is executed against your page's DOM (eg a bookmarklet, or greasemonkey script).

我认为相同的原产地政策可能涵盖这一点: http//en.wikipedia.org/wiki/Same_origin_policy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM