Why client-side validation is a lie
You probably heard it a million times. It is one of the golden rules of web-development. Do not rely solely on client-side validation to ensure you get the data that you expect from the browser. Anyone can send you a crafted request that bypasses your script validation. Always validate on the server as well. And yet, I see a lot of commercial sites that ignore this rule, and it is easy as hell to break their logic. In fact, with the following simple steps I will show, you can bypass any javascript-only validation.
Consider the following TestValidation.htm page:
1 <html >
2 <head>
3 <title>Validation Lies To You</title>
4 <script>
5 var valid;
6 function validate() {
7 valid = document.getElementById('Text').value != "";
8 if (!valid)
9 alert('Not Valid!');
10 return valid;
11 }
12 </script>
13 </head>
14 <body>
15 <form method="post" action="save.aspx" onsubmit="return validate();">
16 <input id="Text" type="text" />
17 <input type="submit"/>
18 </form>
19 </body>
20 </html>
This html page contains a form, a text box and a button. The validate function checks if the form is valid (in this case that the text box contains a value, but it can do any other validation as well). If it is valid, the form will submit to save.aspx, if it is not - an error message is displayed.
In order to bypass this validation we don't have to craft an http-request or play with the script options of our browser. What we need to do is this:
- Install Firebug. This is a great add-on to Firefox that can help you debug web-sites and javascript easily. And also bypass client side validation.
- Point Firefox to our TestValidation.htm. Hit submit. Err, javascript alert. Can't submit. What can we do?
- Open the Firebug console (via the Tools->Firebug menu or the Firebug icon on the status bar).
- Go to the script tab in the Firebug console and place a breakpoint on line 8 in the code (the "if" statement).
- Now hit the submit button, the breakpoint will hit and the page will halt.
This is where we are:
- We want to change the value for the "valid" variable. We go to the console tab (which is somewhat like the VS debugger "immediate" window) and enter "valid=true".
- Now we go back to the script tab and hit F5. The form posts like a charm.
Now you could say I cheated a little by making "valid" a global variable, and indeed I couldn't find in Firebug a way to change the value of a local variable of a function (the console seems to affect only global DOM elements, unlike the VS debugger "immediate" window). But even if it were a local variable I could write in Firebug the following (before clicking the button):
document.forms[0].onsubmit = function(){return true;}
Or simply:
document.forms[0].submit()
The form would have submitted perfectly in both cases, ignoring the client validation.
So we have arrived at the following conclusions:
- Client-side validation is not security. Always validate on the server side as well. ASP.NET's default validators do this for you, but if you use CustomValidator remember to handle its Server_Validate event.
- Firebug is an awesome tool - I wish I had an equivalent for IE (for the meantime I'll have to settle for IE Dev Toolbar).
Happy coding!