Monday, March 16, 2009

Client Side Data Validation: A False Sense of Security

Microsoft defines a Web Application (WebApp) as a software program that uses HTTP for its core communication protocol and delivers Web-based information to the user in the HTML language. Such applications are also called Web-based applications. Although one could create a custom client for such an application, most applications will leverage an existing web browser client such as Internet Explorer, Netscape Navigator, Opera, etc. In this blog, I will be focusing entirely on the set of webapps that leverage a browser on the client side.

There are many benefits of creating a web application. A few of them are:
  • The ability to leverage existing communication infrastructure and protocols
  • The ability to leverage existing client side software (browsers) thus reducing the total development time and related costs.
  • Reduced client-side deployment costs. For most webapps the only software required by a client is a compliant browser.
There is no such thing as a free lunch and webapps are no exception. One of the major cons of webapps is the loss of control over the client software and environment. For example, if a webapp is designed for public access then it may be accessed from machines running different versions of the same browser, different versions of different browsers, different operating systems, and different hardware devices (such as kiosks, cell phones, and PDAs). It is also likely to be accessed by a type of user we affectionately refer to as a “hacker”. The primary objective of a hacker is to gain illegal access and control over your webapp and either cause it to malfunction/crash or expose sensitive data.

That’s where data validation and a properly designed validation framework fit in. No, this is not a typo or misprint. Security details such as SSL, certificate management, firewalls, etc. are important, but provide only the icing on the cake. They don’t guarantee that the cake (i.e. your webapp) is baked well. What I mean is that while these “details” may make it harder for a hacker to find holes in your webapp, they don’t seal the loopholes themselves. That is, they only delay the inevitable hacking of your application. Take SSL as an example. A common misconception is that SSL provides web application security. The fact is that it does not. SSL is used only to encrypt the data between the web browser and the web server, and thus prevents eavesdropping. SSL has no knowledge of your webapp and hence provides no security to it.

As a software consultant, I’ve had the opportunity to not only design and implement webapps but to assess/audit many webapps as well. I often encounter web pages within the application that are very sophisticated with lots of client side JavaScript that perform all kinds of checks on the data entered by the user. Even the HTML elements have data validation attributes such as MAXLENGTH. The HTML form is only submitted upon successful validation of all the data entered. The server side happily performs the business logic once it receives the posted form (request).

Do you see the problem here? The developers have made a big assumption of “control” here. They assume that all users of the webapp will be equally honest. They assume that all users will always access the webapp through the browser(s) that they (the developers) have tested upon. And so on. What they have forgotten is that it is very easy to simulate browser-like behavior through the command line using freely available tools. In fact, almost any “posted” form can be sent by typing in the appropriate URL in the browser window; although an easy way to prevent such “form posting” is to disable GET requests for these pages. But there is no way to prevent any one from simulating or even creating their own browser to hack into your system!

The underlying problem here is that the developers have failed to recognize the main difference between client side validation and server side validation. The main difference between the two is NOT where the validation is occurring such as on the client or on the server. The main difference is in the purpose behind the validation.

Client side validation is merely a convenience. It is performed to provide the user with quick feedback. It is performed to make the application appear responsive and give the illusion of a desktop application.

Server side validation, on the other hand, is a must for building a secure webapp. It is done to ensure that all data sent to the server from the client is valid data, no matter how the data was entered in on the client side.

Thus, only server side validation provides real application level security. Many developers fall into the trap of a false sense of security by performing all data validation only on the client side. Here are two examples to put things in perspective

Example 1
A typical “Logon” page has a textbox to enter a username and another textbox to enter a password. On the server side, one may encounter some code in the receiving servlet that constructs a SQL query of the form "SELECT * FROM SecurityTable WHERE username = '" + form.getParameter("username") + "' AND password = '" + form.getParameter("password") + "';" and execute it. If the query comes back with a row in the results then the user successfully logged in, otherwise not.

The first problem here is the way that the SQL is constructed, but let’s ignore that for this blog. What if the user types in a username such as “Alice’--“? Assuming that there is a user named “Alice” in SecurityTable, the user (or shall we call her “hacker”) successfully logs in. I’ll leave finding out why this happens as an exercise for you.

Some creative client side validation can prevent normal users from doing this from the browser. But what about the case where JavaScript is disabled on the client or for those advanced users (hackers) who can use another “browser like” program to send direct commands (HTTP POST and GET commands)? Server side validation is a must to prevent something like what was described above from happening and hence plugging a security hole in the webapp. SSL, firewalls, and the likes won’t help you here.

Example 2
A typical “User Registration” page for a public but limited access webapp includes several textboxes for user identification and authentication information such Name, SSN, Date of Birth, and other relatively uniquely known information. Once the user has proven her identity, she is issued a username and password to access the protected parts of the system. In special cases, the user may be prevented from directly registering and an “Administrative” user (i.e. the administrator) may have to register the user instead. The administrator uses the same registration page, but checkmarks a special checkbox on the page that tells the system (receiving servlet) to bypass all [special] checks and directly register the user. The JSP that renders the HTML page is smart enough only to include the checkbox if the user accessing the page is an administrator.

So far so good? Not unless there is some server side validation in the receiving servlet. The receiving servlet checks to see if the “bypass checks” parameter is present and if it is then it bypasses all special checks and registers the user. But it must also check to see if the logged in user is an administrator. Even though the JSP page did that when it rendered, the receiving servlet must perform the check again. In this case, the JSP check can actually be considered as part of the client side validation. It was merely done for convenience. After all, we don’t want to confuse regular users trying to register with the extra checkbox, since no matter what they select (checked or unchecked), it’s not going to make a difference. This is because regular users do not have the authority to bypass “authentication” checks. Furthermore, it would not be an impossible task for a hacker to figure out what the name of the checkbox was and manually issue a registration request with the checkbox name included in the request (with its value set to “checked” of course). Therefore the receiving servlet must check the identity of the logged on user (if there is a user logged on) and only allow an administrator to bypass special checks in the registration process.

Remember, client side validation is for convenience and server side validation is for security. You must always perform at least as much validation on the server as you perform on the client. All properly designed validation frameworks, such as the Struts Validation Framework, handle this for you. Feel free to leave me a comment and let me know your thoughts…

No comments:

Post a Comment