Guideline Item Template Example

Do not rely on client-side validation for security purposes

Applies to

  • ASP.NET 1.1
  • ASP.NET 2.0

What to Do

Do not rely on client-side validation for security purposes. Use server-side validation to ensure that data is safe and perform security decisions based on that. Client-side validation should be used solely to reduce round trips to the server and to improve the user experience.

Why

Client side validation can be easily bypassed. For example, a malicious user could disable the client-side script routines by disabling JavaScript. Users may also construct their own form posts using custom html, or using an HTTP proxy to modify form posts. If developers rely on the controls in the client's user interface and do not validate all results on the back end, it may introduce injection vulnerabilities that would allow an attacker to bypass data input restrictions and gain access to unintended application functionality.

When

During implementation, ensure all input from the client is validated, even if the input is not stored.

How

It's important to specify what input is acceptable, rather then trying to specify all the variations of input that are illegal (whitelisting as opposed to blacklisting). Use ASP.NET validator controls to check user input on the server side and provide feedback to the user when input fails to pass validation requirements. Follow these steps on each form page in an application:

1. Determine the required fields. Use the required field validator control to ensure all required fields are present. Here is an example that declares a textfield in an ASP page that is a required field:

<td> <asp:RequiredFieldValidator runat=server ControlToValidate=txtName ErrorMessage="User ID is required."> * </asp:RequiredFieldValidator></td><td>User ID:</td><td><input type=text runat=server id=txtName></td>

The * is displayed next to the label if the input is blank. The error message is reported in a summary. The "ControlToValidate" property specifies the ID of the control to validate. The final step is to add a validation summary to the top of the page like so:

<asp:ValidationSummary runat=server HeaderText="There were errors on the page:" />

2. Enforce numeric range constraints. Use the RangeValidator control to ensure any numeric values are constrained to a specific, acceptable range. Here is an example that declares an integer field in an ASP page that has a valid range from 1 to 50:

<td>

<asp:RangeValidator id="Range1" ControlToValidate="txtState" MinimumValue="1" MaximumValue="50" Type="Integer" EnableClientScript="false" Text="The value must be from 1 to 10!" runat="server"> *
</asp:RangeValidator></td><td>State:</td><td><input type=text runat=server id=txtState></td>

3. Validate verification fields. Fields such as password entry are often verified by having the user re-type them to ensure they are correct. Use the CompareValidator control to make the comparisons and ensure validity/integrity. Here is an example that declares two password fields in an ASP page that must match in order to validate properly:

<asp:CompareValidator runat=server

ControlToValidate=txtRePWord
ControlToCompare=txtPWord
ErrorMessage="Passwords do not match." />

In this case, the two fields being compared are "txtPWord" and "txtRePWord". If they do not match, validation fails with the error message, "Passwords do not match.".

4. Enforce type constraints on string fields. String fields are the most difficult type of input to effectively validate because the range of acceptable characters is much larger then numeric and enumerated types. Regular expression provide a flexible mechanism for dictating valid patterns and characters. Use the RegularExpressionValidator to perform a variety of checks on string-based fields such as zip codes and phone numbers. Here is an example that declares an text field in an ASP page that should represent a five digit zip code, consisting entirely of numberic digits, and a validator to enforce those constraints:

<input type=text runat=server id=txtZip>

<asp:RegularExpressionValidator runat=server
ControlToValidate="txtZip"
ErrorMessage="Zip code must be 5 digits, all numbers."
ValidationExpression="0-9{5}"> *
</asp:RegularExpressionValidator>

<td>Zip code:</td><td><input type=text runat=server id=txtZip></td>

5. Use custom validation to handle remaining input constraints. The built-in ASP.NET validation controls handle most of the cases that commonly arise in web applications, but there may be times when they are not appropriate. The CustomValidator enables custom validation code that can plugs into the existing validation system. Here is an example that declares a text field in an ASP page. For this particular text field, there is business logic that needs to be satisfied which is not easily constrainable by the other validation constructs, so a custom validator is implementated that ensures the string in the text field does not start with the letter "a":

<%@ Page Language="vb" %><script runat=server>

public sub CheckID(source as Object, args as ServerValidateEventArgs) args.IsValid = args.Value.substring(0, 1).tolower() <> "a"end sub

</script>

To call this function, add a CustomValidator, which is designed to call developer code to perform its check. Here is the declaration:

<asp:CustomValidator runat=server controltovalidate="txtName" errormessage="ID is already in use." OnServerValidate="CheckID" />

It is worth noting that this could have been done with the RegularExpression validation control, but in this case it makes more sense to use custom validation since a type of high-level validation that could conceivably be more complex then a simple pattern match is being defined (e.g., the validation rules might change based on application state).

Problem Example

Consider a very simple form for an online shopping cart. The cart component consists of two components:

1. An HTML form that contains all of the fields that make up the order to be submitted for processing:

<html> <head> <title>Widget shopping cart</title> </head> <body> <H1>welcome to the most boring shopping cart on the web!</H1>

A widget's current price is $19.95 USD. Please use the following form to submit an order.
<form action="process_order.aspx" method="POST"> <p>Please enter the number of widgets you would like to purchase:</p> quantity:<br/> <select name="WidgetQuantity"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select>
... <input type="submit" value="order"/> </form>
</body></html>

2. An ASP.NET page that processes the form submissions and performs the necessary steps to create the order.

int dQuantity = Request("WidgetQuantity");double dPrice = 19.95;

double dCost = dQuantity * dPrice;

This server side page is problematic because it lacks validation to ensure the quantity field is correct. The application works fine in the case where a user plays by the rules and submits the form as it is shown, because the quantity field ensures that the range constraints for the order quantity are always valid. However, if a clever user decides to construct their own form and submits a negative WidgetQuantity field, it causes a negative balance. Depending on what e-commerce system is used, this could result in a credit to the user's account. It also might subtract the negative balance from the company's inventory, which would carry significant ramifications and costs later on.

Solution Example

Consider the following ASP.NET page that processes the form submissions and performs the necessary steps to create an order:

<%@ Page Language="vb" %><script runat=server>public sub OnSubmit(source as Object, e as EventArgs) if IsValid then ' Now we can perform our transaction. int dQuantity = Request("WidgetQuantity"); double dPrice = 19.95; double dCost = dQuantity * dPrice; end ifend sub</script><html><head><title>Validation Sample</title></head><body>

<form runat=server><asp:ValidationSummary runat=server headertext="There were errors on the page:" />

<table> <tr> <td> <asp:RequiredFieldValidator runat=server controltovalidate="WidgetQuantity" errormessage="WidgetQuantity is required.">* </asp:RequiredFieldValidator> </td> <td>A widget's current price is $19.95 USD. Please use the following form to submit an order.</td> <td> <select name="WidgetQuantity"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> <asp:RegularExpressionValidator runat=server display=dynamic controltovalidate="WidgetQuantity" errormessage="WidgetQuantity must be a non-zero, positive integer." validationexpression="1-9{1}0-9{0,7}" />

</td> </tr>...</table><br><input type=submit runat=server id=cmdSubmit value=Submit onserverclick=OnSubmit></form></body></html>

The ASP.NET Validator control provides client-side validation to reduce roundtrips to the server and improve user experience, but also provides server-side validation to ensure that the widget quantity field is a positive integer. It is also validated as a required field that must be provided before submitting the order.

Additional Resources

  • User Input Validation in ASP.NET http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/pdc_userinput.asp
  • Validation Server Control Syntax http://msdn2.microsoft.com/en-us/library/e5a8xz39.aspx
  • General Purpose Code Injection article http://en.wikipedia.org/wiki/Code_injection

Related Items

  • Application does not rely on request only validation
  • Free form input is sanitized to clean malicious data
  • All the input is validated for length, range, format, and type
  • Input is checked for known malicious types and patterns.

Last edited Apr 1, 2007 at 12:26 AM by mycodeplexuser, version 3

Comments

No comments yet.