7

Are there ways to prevent, or make it difficult enough, for someone to inject Javascript and manipulate the variables or access functions? A thought I had is to change all var names randomly on each reload so the malware script would need to be rewritten every time? Or are there other less painful ways?

I understand that eventually someone will hack his way in, but I'd like to know ways to make it difficult to reproduce the action, so that people won't publish a bookmarklet or something similar for everyone to use. I don't care if experts find their way in the code, but I'd like it to be a bit more complex than javascript:d=0;

If you know ways to make hacking Javascript a bit more difficult, please write those.

stagas
  • 4,607
  • 3
  • 28
  • 28
  • 2
    Obfuscation goes part of the way. – Artelius Jul 07 '10 at 12:29
  • 2
    Difficult? Yes. Difficult enough? Never for real security (but it may be enough to stop easy cheating in games or whatever). – Bart van Heukelom Jul 07 '10 at 12:44
  • 1
    I suppose the question is "why does it matter?" If there's state sent to the server, relying on guards at the JS end is bad practice, if no data is sent then who loses? – spender Jul 07 '10 at 12:50
  • 2
    @splender - I used to work on a site that had the most viciously awful ad code. Most of it was written by agencies whose programmers knew flash pretty well, but couldn't program JS to save their lives. A lot of it was cut-and-past from 1998. We weren't careful about our own JS namespaces and several times a year, an ad would overwrite something we were needed and the site would break. Proper namespacing and using private members unless necessary made most of these problems go away. So they can go on being crappy and we can go on running a site. – Andrew Jul 07 '10 at 13:04

4 Answers4

23

Accept that your javascript will be "manipulated" and make provision at the server side. There's fundamentally nothing you can do to stop people tinkering with the client.

spender
  • 117,338
  • 33
  • 229
  • 351
  • Thanks, I was thinking of a way to make it difficult, it's not really vital to prevent manipulation, but I'd like to prevent at least someone posting a bookmarklet to 'do that cool thing' so everyone can hack. I don't really care if an expert finds eventually a way, but I'd like it to be difficult enough for noobs, and maybe hard to reproduce the action without using tools if that's possible. – stagas Jul 07 '10 at 12:37
  • 3
    I agree with @spender. The problem with your scenario is that the best you can do is security through obscurity. It will cost you a lot of time and effort and will never fully solve the problem, so you will always have to do it in the server side as well. – flpmor Jul 08 '10 at 11:33
  • I can't concur enough. Security through obscurity is a bad idea. You need to do server-side verification. Period. – g.d.d.c Jul 16 '10 at 18:51
12

You can write your JS to use only private methods and variables in a self-executing function. For example, the following code leaves no sign of itself in the global namespace for anyone to monkey with.

(function(){
    var x = 1;
    var y = 2;
    var z = "A am z";
    var clickHandler = function() {
        alert('You clicked the body');
    };
    document.getElementsByTagName('body')[0].addEventListener('click',clickHandler,true);
}());

[EDIT] The above code is susceptible to a user overwriting any globally available objects, methods, events or properties you are using (in this case, document, getElementsByTagName and addEventListener), so if you are truly paranoid you can copy these to your function scope before the page has loaded and the user has a chance to overwrite them. Using addEventListener is a good idea because unlike the event body.onclick, it cannot be removed or overwritten from outside the function.

Andrew
  • 14,204
  • 15
  • 60
  • 104
  • 2
    You have an error in the last line it should be `})();` I think – stagas Jul 07 '10 at 12:51
  • I used to write it that way until Crockford got into my head. Except for a missing semicolon (which I will add), the above code does validate according to JSLint; – Andrew Jul 07 '10 at 12:54
  • @Andrew: Hmm can you explain the difference of `}())` and `})()` I was aware of self-executing functions but I don't understand what you just did. – stagas Jul 07 '10 at 13:01
  • 1
    I honestly don't know what difference it makes except that Douglas Crockford says the invocation needs to be entirely inside. Knowing him, there is a very good, very arcane reason. I only know this because my JSLint validator kicks up two warnings when I have the invocation parenthesize outside. The warnings are: `Move the invocation into the parens that contain the function.` and `Wrap the entire immediate function invocation in parens.` Well, I was tired of JSLint hurting my feelings so now I do what it says. We're both happier that way. – Andrew Jul 07 '10 at 13:09
  • @stagas - Now that I've looked around, it seems that it is an issue purely of style. The top answer by @altCognito on [this SO thread](http://stackoverflow.com/questions/939386/javascript-immediate-function-invocation-syntax) points to Crockford's own explanation. Basically, the parenthesize around the function either draws attention to the unexecuted function or the result of it and Crockford thinks it should point to the result. So, basically, it's splitting hairs. – Andrew Jul 07 '10 at 13:20
  • @stagas - That's spats-and-a-top-hat stylish. The only thing that matters to me is readability and thankfully there are lots of ways to write clear, understandable code. Fab code is *very* clear (though I hate it when I have to jump back and forth between 20 1-kilobyte files to follow what is happening in the code). I use most of Crockford's style because I program alone and JSLint really, really helps me catch stupid mistakes, typos, variables I've let escape into the global namespace. I actually disagree with a lot of his style and pedantics, but he's helped me grow more than anyone else. – Andrew Jul 07 '10 at 14:02
  • +1 for being the only person to actually answer stagas's question. – Steve Elmer Jul 17 '10 at 10:06
  • 4
    One extra layer of security is to pass in the document, window, body and undefined variables to your JS, so they are local to the function. `(function(document, window, undefined){ [...]})(document,window);` – Aaron Butacov Jul 24 '10 at 17:00
0

Any user that will really want to tamper with the client will be able to. The code is on his machine. Even if you obfuscate the client side code, there are tools out their that will help someone deobfuscate the code back in a second.

What you need to think about though is making the site safe on the server, and safe for other users as well. This means (as a minimum):

  1. Checking/Validating every request and input parameters on the server so Users won't be able to alter any server side data by triggering 'hacked' client side functions you wrote.

  2. Check all data that you output to the screen that was originated from user input. Other users might have inserted client side scripts that are dangerous for your site, and especially dangerous to the other users on your site. (If you're using .net then check out the AntiXSS library)

Ganj Khani
  • 1,229
  • 15
  • 20
gillyb
  • 8,760
  • 8
  • 53
  • 80
-1

Obfuscation and minification should make it a good bit more difficult to hack, but I agree with spender.

JoshNaro
  • 2,047
  • 2
  • 20
  • 40