views:

108

answers:

4

I am trying to build some sort of a javascript "antivirus" that would try to catch particular function calls.

So lets say I've got some random javascript file, can I check if it doesn't use function jQuery.trim() (just for example sake) anywhere?

It seems like pretty complicated task, plus there are eval and base encodings which could transform any code to a pile of characters.

Would it be possible to write something like this in PHP? Are there any libraries and tools that could help?

+2  A: 

Before any script runs you could set each of the functions you don't want to run to your own function, which for example could log that the script tried to run this function Say you didn't want the script to use eval:

window.eval = function(){
     console.log("The script tried to call eval");  
};

or if you didn't want it to call indexOf on strings

String.prototype.indexOf = function(){
     console.log("The script tried to call indexOf on the string" + this);
}

Edit: If you want to continue using the functions you can create copies and then execute them inside your replacement function like so:

    var evalCopy = window.eval;
    window.eval = function () {
        console.log("Eval was called again");
        return evalCopy.apply(this,arguments);
    }
pixl coder
Thanks, but I am trying to do something a little different - not prevent script from using a function, but to answer a question - is this function called or not.
serg
The drawback with this is that this disables the functions for all scripts, not just the ones he wants to disallow them on. It sounds like he wants to accept user created scripts and disallow certain functions, but not globally (including for his own scripts).
CD Sanchez
@serg and then what are you going to do once you determine that information? Allow it to execute anyway?
Alex JL
@Alex I only need it for statistics - so I can display whether or not this code is using particular functions.
serg
Could you do this:var evalCopy = window.eval;window.eval = function(input){ console.log("Eval was called again"); return evalCopy(input);}. Sorry this isn't very readable. I edited my answer :-)
pixl coder
A: 

There's a PHP Javascript parser and tokenizer that might help. You could look through the parse tree for function calls, as well as aliases to make sure users don't assign the function to another name and then use that new name. Once you disallow eval and similar functions (e.g., Function, setTimeout, etc.), encoded content shouldn't be a problem since eval is required to execute the code.

http://web.2point1.com/2009/11/14/jparser-and-jtokenizer-released/

Example of parse tree: http://timwhitlock.info/plug/examples/JavaScript/JParser.php

EDIT: Nevermind, even this wouldn't catch some of the edge cases. The only other thing I could think of would be to run the code through a Javascript engine and monitor for any evil function calls. But even that wouldn't catch everything (data from a remote server is one example).

CD Sanchez
Thanks. The only problem is that it doesn't handle eval. I run their example code through packer and it couldn't extract function names.
serg
@serg: Could you post the minified code? You can add it to some sort of pastebin or edit it into your post.
CD Sanchez
+2  A: 

No. You can not make this determination in general by merely inspecting the code.

Even if you ignore eval (easier said than done--there are lots of ways to hide a function call), it's still not decidable.

For example:

somestring[data_from_remote_server](...)
where data_from_remote_server is "indexOf". That code can call indexOf. Is it likely to? Who knows.

Even without a remote server, it's not hard to imagine writing code that computes the string "indexOf" without actually containing the string "indexOf".

blucz
+2  A: 

JavaScript is a dynamic language and even without functions like eval, it becomes very difficult to figure out if a script is calling a particular function. The best solution I can think of is similar to @pixl coer's to override the function itself, and selectively call it instead of always blocking it.

Consider this example that calls the pop method on an Array indirectly by referring to it as a broken string.

var p = 'p';
var o = 'o'
[2,3,4][p + o + p]();

By wrapping the actual method, you can selectively decide whether to let the method pass through or block it at runtime.

However, note that even this is not fool-proof. Each iframe gets it own copy of the methods such as eval. Somebody could just create a disposable iframe, get the eval method from there and then execute it.

Is short, this determination can not be made statically at all. Even dynamically, you would have to patch up a lot of things to ensure that a particular function never gets called.

Anurag