- Black Boxes Versus White Boxes
- The Web Application as an API
- Specific Security Mistakes
- Security through Obscurity
- Conclusions
Security through Obscurity
Admittedly, the root problem in all of the specific design and implementation mistakes we've mentioned is not the increased transparency caused by Ajax. In MyLocalWeatherForecast.com, the real problem was the lack of proper authorization on the server. The programmers assumed that because the only pages calling the administrative functions already required authorization, then no further authorization was necessary. If they had implemented additional authorization checking in the server code, then the attacks would not have been successful. While the transparency of the client code did not cause the vulnerability, it did contribute to the vulnerability by advertising the existence of the functionality. Similarly, it does an attacker little good to learn the data types of the server API method parameters if those parameters are properly validated on the server. However, the increased transparency of the application provides an attacker with more information about how your application operates and makes it more likely that any mistakes or vulnerabilities in the validation code will be found and exploited.
It may sound as if we're advocating an approach of security through obscurity, but in fact this is the complete opposite of the truth. It is generally a poor idea to assume that if your application is difficult to understand or reverse-engineer, then it will be safe from attack. The biggest problem with this approach is that it relies on the attacker's lack of persistence in carrying out an attack. There is no roadblock that obscurity can throw up against an attacker that cannot be overcome with enough time and patience. Some roadblocks are bigger than others; for example, 2048-bit asymmetric key encryption is going to present quite a challenge to a would-be hacker. Still, with enough time and patience (and cleverness) the problems this encryption method presents are not insurmountable. The attacker may decide that the payout is worth the effort, or he may just see the defense as a challenge and attack the problem that much harder.
That being said, while it's a bad idea to rely on security through obscurity, a little extra obscurity never hurts. Obscuring application logic raises the bar for an attacker, possibly stopping those without the skills or the patience to de-obfuscate the code. It is best to look at obscurity as one component of a complete defense and not a defense in and of itself. Banks don't advertise the routes and schedules that their armored cars take, but this secrecy is not the only thing keeping the burglars out: The banks also have steel vaults and armed guards to protect the money. Take this approach to securing your Ajax applications. Some advertisement of the application logic is necessary due to the requirements of Ajax, but always attempt to minimize it, and keep some (virtual) vaults and guards around in case someone figures it out.
Obfuscation
Code obfuscation is a good example of the tactic of obscuring application logic. Obfuscation is a method of modifying source code in such a way that it executes in exactly the same way, but is much less readable to a human user.
JavaScript code can't be encrypted because the browser wouldn't know how to interpret it. The best that can be done to protect client-side script code is to obfuscate it. For example,
alert("Welcome to JavaScript!");
might be changed to this:
a = "lcome to J"; b = "al"; c = "avaScript!\")"; d = "ert(\"We"; eval(b + d + a + c);
These two blocks of JavaScript are functionally identical, but the second one is much more difficult to read. Substituting some Unicode escape characters into the string values makes it even harder:
a = "\u006c\u0063\u006fme t\u006f J"; b = "\u0061\u006c"; c = "\u0061v\u0061Sc\u0072ipt\u0021\")"; d = "e\u0072t(\"We"; eval(b + d + a + c);
There are practically an endless number of techniques that can be used to obfuscate JavaScript, several of which are described in the "Validating JavaScript Source Code" section of Chapter 4, "Ajax Attack Surface." In addition, there are some commercial tools available that will automate the obfuscation process and make the final code much more difficult to read than the samples given here. HTML Guardian™ by ProtWare is a good example. It's always a good idea to obfuscate sensitive code, but keep in mind that obfuscation is not the same as encryption. An attacker will be able to reverse engineer the original source code given enough time and determination. Obfuscating code is a lot like tearing up a bank statement—it doesn't make the statement impossible to read, it just makes it harder by requiring the reader to reassemble it first.