AJAX *IS* Secure
A few days ago, Mano (Emanuel) Cohen-Yashar, Sela's international lecturer, wrote a post in his blog under the title "AJAX is not secure".
Please note that this post was written as a technical reply, and does not by any how represent anything else. I'm subscribed to Mano's blog, and reading it always anxiously. I was the first one to reply his post (In Hebrew, please accept my apology, but it was published on an Israeli platform), and I appreciate Mano's opinion, even if I oppose it.
Claiming a technology is not safe is somewhat ignorance (and I must admit I used to do it back then...). Saying "AJAX is not safe" is like saying "Dogs are not safe". Adopt one - and it's nice at the beginning.. Don't take it to the vet - it'll get sick and contagious; most important: If you won't treat it with "respect", it'll bite you.
It's not AJAX which is not safe. Some of its implementations might not be safe.
I've decided to dedicate this post to break some misconceptions regarding not only AJAX, but any other technology referenced as "insecure". Also, I'll try to provide some basic rules of thumb for any development of software. Web/Win, Microsoft/Mac/Linux, C#/Java etc..
I've quoted Mano's post, with my assertions inside.
AJAX is the new Hot technology concerning web application. It allows the client to do much more than it used to and to achieve a much better user experience.
So first, AJAX is maybe a Hot technology, but it sure is not new (at least, it's concept is not new, nor it's implementation...). Unless C# is new, AJAX (formerly known by other names, such as XMLHTTP ActiveX etc.) is not new. It's here for over a decade.
It's true that its real hotness was discovered in the past 5 years, since Gmail took it one step further in implementation, but it's sure not new.
I, myself, created a dynamically loaded XML sites using simple JS calls on IE 6.0, on 2002.
AJAX is based on XmlHttpRequests that the browser creates while the page is presented on the browser. The client does not know that under the cover so many requests are being sent. Ajax is a java script technology running mostly on the client side and on the server the following question arises: will the average AJAX-enabled web-application be able to tell the difference between a real and a faked XmlHttpRequest?
The answer is NO. AJAX is a client side technology and we all know that the client should not be trusted.
The answer is - YES, or at least - No difference from regular HTTP Requests (e.g. HTML/ASPX/ASP/PHP etc..).
Web developers had the problems if forms impersonation since ever. That's the reason why technologies like CAPTCHA were adopted by the community, to avoid bots which are replacing the original form with an automatic POST/GET generator.
Although, we always had (and will always have) problems (due to the Real IP Barrier) authenticating the client with the server (Cookies, HTTP headers, Sessions and other keys can always be impersonated by sniffers and other HTTP altering mechanism) - Using any HTTP request-respond we can ensure, ONLY, that a specific IP made the requests. In case of a NAT or other IP sharing techniques, we should accept cases where packets were intercepted by a sniffer, and impersonated later on. That's why, for instance, we might prefer working with some basic encryption or authentication mechanisms (e.g. SSL, encrypted passwords and other POST strings etc..).
Anyhow, I guess what I'm trying to say is that the same problem is feasible both for AJAX and regular synchronous HTTP requests. AJAX changed nothing, nor added any new complication for that method.
This makes AJAX a much more difficult technology to protect. We all know how difficult is to bring application security to traditional server application. For AJAX it is double the effort.
How does it make it more difficult to protect than regular ASP.NET? Why is it doubling the effort? Using, for instance, HTTPS as the infrastructure for the web-services which are being consumed by the AJAX is as safe as using HTTPS as the infrastructure for a regular ASP.NET finance application.
However, let's don't forget why programmers, developers and software engineers still hold positions in enterprises. Our job is to predict those security weaknesses, and to provide an answer. Since day 1 in the academy, programmers are being told - Never trust input from the user. Input should be double checked. Once, on the client side (and it does not matter if the client is a web application or a win application) - And once again on the server side, before starting to analyze the data. Speaking more strictly, you should check your data THREE times. Third time is before inserting the data into a Database, by using Stored Procedures and strict validation on INSERTs and UPDATEs.
It does not make the AJAX more complex. It makes our life more complex. If you can't stand the heat, get out of the kitchen.
AJAX is advancing rapidly and new frameworks are introduced frequently but none can secure the AJAX application in a reasonable manner.
Choosing an infrastructure/framework is an important process in every project. However, it seems it is sometimes neglected.
When an organization performs his checks prior to choosing an infrastructure for his application (Whether it may be Java versus .NET, Windows vs. Linux, DevExpress vs. Infragistics etc..), its technological experts should be familiar with the internal requirements (In terms of Performance, Scalability, Security etc.). It's true that a failure in the infrastructure may cause a lot of trouble later on. However, when choosing the infrastructure you should ask yourself some WH questions, and do the math:
WHO
- Who is the vendor behind it? This might be the most important question one should ask himself. Sometimes, the open community is just not good enough. I prefer paying for a service, knowing I'll get the best support available (Even if it will cost the vendor with a dedicated programmer for a given period of time). When I am choosing an open-source infrastructure, I make sure first that its license fits my needs, and that I do have the amount of support to feel confident in case things go wrong.
- Who is going to assimilate it from my organization? It took me years to realize that people make software, and not vice versa. Therefore, if my developer prefers a certain infrastructure he feels comfortable with, I might give it a chance.
HOW
- How am I going to use it? Is it going to be my application's base tier, or is it going to feel a very specific need? Am I going to use it 'as is', or will I need to customize it? Will I use 1% of it's features, or am I going to fully utilize it?
- How tightly coupled am I going to be with it? Will I be able to switch to another infrastructure later on, or is it going to be a catholic wedding? Will I be able to move from one platform to another?
- How am I going to deal with missing features? Will I have to develop workarounds, or use another complementary infrastructure? Am I going to change the code of the infrastructure itself?
WHAT
- What are the alternatives? Is there any other tool providing the same (80:20) functionality? Should I develop my own infrastructure on premises? Maybe I... just don't need it?
- What support do I have in case something goes wrong? What is the obligation of the vendor? Do I have any sources of information to consult? Books? Professionals? Web communities?
- What if it fails? Am I doomed? Is there any data loss? Can I quickly move to an alternative? Is it a show stopper?
WHEN
- When this product was first announced? What is its legacy?
- When was the current version released? What were the bugs fixed in this version, and what are the feedbacks from other users? What was the last major release? Maybe the current version is already obsolete?
- When will the next version be released? Is the product still being developed? Any future?
WHY
- Why, in the first place, do I need it? It's often software engineers are using a utility because it's neat. Do I really need it? Maybe it's a solution for a problem I don't really have?
After answering those questions and other questions you might ask yourself, you should be able to spot the not. If you decided to go with an infrastructure after filling this questionnaire, you should at least know what your chances are, and what you should do in case things went wrong.
From a business and an architectural point of view unfortunately today we have to make a tradeoff. Security versus User Experience.
I sure DO NOT think that's true. I don't see why User Experience should come in place of Security. This statement is not only too generic (Does the fact the login screen in Windows 7 is much more colorful and supportive (including the password hint feature..) makes it any less secured than Windows 2000's?), but it is also outrageous! Binding User Experience with Security is like binding Beer with over weight. The fact you consume the first, won't necessarily cause the other. Sure, you can exaggerate, but then again - you can always burn those calories at the gym.
Proper design can use AJAX in a sandbox. This means less sensitive areas of the application can enjoy AJAX but around the sensitive business and information an "AJAX Firewall" is built. For example there will be no AJAX enabled Web Service that exposes sensitive information.
A Proper design should separate any user related logic, any UI logic, and business logic from each other. Most important - if you web-service knows it's being consumed from an AJAX call, dude - you're in deep shit. A web service should provide an output to a given input. The AJAX script should interpret that output for its needs.
I, for instance, am testing all of my web services using regular NUnit winform interface. My AJAX code is calling those services later on... goes without saying there is no difference between the input from the AJAX and the input from my testers.
If you do need to implement some AJAX remember that AJAX enables new XXS capabilities and so server validation must be much more strict. Not only the body of the http packet must be validated but all of its headers.
I don't get it. What can be done with AJAX which was not done with regular HTTP queries? The only difference is that with regular HTTP responses, the browser is checking the response code, while with AJAX you check the response code yourself. You should never assume a certain input. For instance, you should never assume that if you get a 4xx or a 5xx response from the server, the call failed.
It is possible that the web-service actually executed its code, but failed somewhere. That's why, when dealing with web or any other technology, you should take in consideration, while you are still during the design phase, the places where you should use transactional mechanism. Those are places where data is being altered. Define a variety of responses for your services. Errors should be followed with explanations. For instance - The given data already exists. The given Token was already used. Etc...
Working with Sessions and Tokens is important also in regular browsing. I cannot count the amount of bugs I've seen during my life, which had to do with a user pressing the back button in his browser, re-submitting a certain form, or a user double-clicking the submit button... Those things should be taken in consideration. But once again, it has nothing to do with AJAX.
Never trust a third party. AJAX applications fetch information from various untrusted sources such as feeds, blogs, search results. If this content is never validated prior to being served to the end browser, it can lead to dangerous cross-site exploitation.
This is a bit ambiguous for me.. AJAX as a technology, won't allow cross-site scripting. Earlier versions of both Internet Explorer and FireFox had several exploitations which allowed cross-domain/cross-site scripting. Today, with IE8/7 and all service packs, and FF3+, there is no way (that I'm aware of) to asynchronously call a service from another domain. That's why blogs, feeds, search results etc, should be wrapped with server-side code (running locally) first, and cannot be consumed by the XmlHttp object from the browser.
Also, as said before - content should always be verified whether incoming or outgoing, whether on the server side or on the client side. You should never trust your data, and you should never ever trust someone else's data.
With AJAX, a lot of the logic is shifting to the client-side. This may expose the entire application to some serious threats.
That's true. It should be taken in consideration during the top level design phase, and be treated both on the client side and server side, as described earlier.
The urge for data integration from multiple parties and untrusted sources can increase the overall risk factor as well: XSS, XSRF, cross-domain issues and serialization on the client-side and insecure Web services, XML-RPC and REST access on the server-side.
It's indeed true that misusage of AJAX might cause new types of XSS. However, even the simplest HTML form element might cause XSS. Regarding insecure Web-Services, RESTfull interfaces etc... those should be handled both on the server side scripts, just like any other ASP/PHP/Perl/... script - and, by the webserver itself.
Never underestimate the need of good IT infrastructure. Security does not start nor ends with secure source code, which is taking everything in consideration. Security is much wider. Server policies, permissions, users and groups, RWX file permissions... all of those might have to do with the integrity of your software.
Some web servers would allow HTTP DEL requests upon files with public 666 permissions (or any **6 **7).
Conversely, Ajax can be used to build graceful applications with seamless data integration.
However, one insecure call or information stream can backfire and end up opening up an exploitable security hole.
These new technology vectors are promising and exciting to many, but even more interesting to attack, virus and worm writers.
To stay secure, first answer the question is AJAX really needed? Then make sure it lives in a sandbox and third make sure your developers are paying attention to implementation details and taking security into consideration.
blog comments powered by