ASP.NET 2.0 Security Inspection Questions - Input and Data Validation

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Jason Taylor, Rudolph Araujo


Contents

Input and Data Validation Vulnerabilities and Implications

Vulnerability

Implications

Unvalidated and untrusted input in the HTML output stream

The application is susceptible to cross-site scripting attacks.

Unvalidated input used to generate SQL queries

The application is susceptible to SQL injection attacks.

Reliance on client-side validation

Client validation is easily bypassed.

Use of input file names, URLs, or user names for security decisions

The application is susceptible to canonicalization issues, which can lead to security flaws.

Application-only filters for malicious input

This is almost impossible to do correctly because of the enormous range of potentially malicious input. The application should constrain, reject, and sanitize input.


If you make unfounded assumptions about the type, length, format, or range of input, your application is unlikely to be robust. Input validation can become a security issue if an attacker discovers that you have made unfounded assumptions. The attacker can then supply carefully crafted input that compromises your application. Table 3 shows a set of common input and/or data validation vulnerabilities and their implications.

Use the following questions when you review your code's input and data validation:

  • Does the code validate data from all sources?
  • Does the code use a centralized approach to input and data validation?
  • Does the code rely on client-side validation?
  • Does the code accept path or file-based input?
  • Does the code validate URLs?
  • Does the code use MapPath?


Does the code validate data from all sources?

Make sure that your code makes no assumptions about the validity of input data. Code should assume that input data is malicious. Use the following questions to guide your review.

  • Does the code validate form field input?

The application should not contain code similar to the following example.

<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtName" runat="server"></asp:TextBox>
</form>
 

Instead, the text is validated using the RegularExpressionValidator control, as shown in the following example.

<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtName" runat="server" />
<asp:RegularExpressionValidator 
  id="nameRegex"
  runat="server"
  ControlToValidate="txtName"
  ValidationExpression="^[a-zA-Z'.\s]{1,40}$"
  ErrorMessage="Invalid name" 
 />
</form>
 
  • Does the code validate query string and cookie input?

The application should use code similar to the following.

// Request.QueryString
// Instance method:
Regex reg = new Regex(@"^[a-zA-Z'.\s]{1,40}$");
Response.Write(reg.IsMatch(Request.QueryString.Get("Name")));
// Static method:
if (!Regex.IsMatch(Request.QueryString.Get("Name"),@"^[a-zA-Z'.\s]{1,40}$")) 
{
 // Name does not match expression
}
// Request.Cookies
// Instance method:
Regex reg = new Regex(@"^[a-zA-Z'.\s]{1,40}$");
Response.Write(reg.IsMatch(Request.Cookies.Get("Name")));
// Static method:
if (!Regex.IsMatch(Request.Cookies.Get("Name"),@"^[a-zA-Z'.\s]{1,40}$")) 
{
 // Name does not match expression
}
 
  • Does the code validate data that is retrieved from a database?

Your application should validate this form of input, especially if other applications write to the database. Do not make assumptions about how thorough the input validation of the other application is.

The application should not contain code similar to the following example.

SqlConnection conn = new SqlConnection(connString);
SqlCommand sqlCmd = new SqlCommand("SELECT CustomerID FROM Orders WHERE OrderID=1", conn);
SqlDataReader dr = sqlCmd. ExecuteReader ();
dr.Read();
string s = dr[0].ToString();
int val = Int32.Parse(TextBox1.Text);
 

Instead, the code should contain code similar to the following.

SqlConnection conn = new SqlConnection(connString);
SqlCommand sqlCmd = new SqlCommand("SELECT CustomerID FROM Orders WHERE OrderID=1", conn);
SqlDataReader dr = sqlCmd. ExecuteReader ();
dr.Read();
string s = dr[0].ToString();
if (!(Int32.Parse(s) < 6))
    Response.Write("Throw an error");
int val = Int32.Parse(TextBox1.Text);
 
  • Does the code validate Web method parameters?

Web services are just as vulnerable as standard Web forms to input manipulation attacks like SQL injection. Make sure your code validates Web method parameters as shown here.

[WebMethod]
public decimal RetrieveAccountBalance(string accountId)
{
 if (!Regex.IsMatch(accountId,@"^[a-zA-Z'.\s]{1,40}$")) 
 {
   // AccountID does not match expression
   // do not process request
 }
}


Does the code use a centralized approach to input and data validation?

For common types of input fields, examine whether or not the code uses common validation and filtering libraries to ensure that validation rules are performed consistently and it has a single point of maintenance.


Does the code rely on client-side validation?

Client-side validation can reduce the number of round trips to the server, but do not rely on it for security because it is easy to bypass. Validate all input at the server.

It is easy to modify the behavior of the client or just write a new client that does not observe the same data validation rules. Consider the following example.

<html>
<head>
<script language='javascript'>
function validateAndSubmit(form)
{
  if(form.elments["path"].value.length() > 0)
  {
     form.submit();
  }
}
</script>
</head>
<body>
<form action="Default.aspx" method="post">
<input type=text id=path/>
<input type=button onclick="javascript:validateAndSubmit(this.parent)" Value="Submit" />
</form>
</body>
</html>
 

In this example, client-side scripting validates that the length of the "path" is greater than zero. If the server processing of this value relies on this assumption to mitigate a security threat, then the attacker can easily break the system.


Does the code accept path or file-based input?

Determine whether your application uses names that are based on input to make security decisions. If it does, your code is susceptible to canonicalization issues. For example, does it accept user names, file names, or URLs? These are notorious for canonicalization issues because of the many ways that the names can be represented. If your application does accept names as input, make sure that they are validated and converted to their canonical representation before processing.

The application should use code similar to the following.

string fileName = Request.QueryString.Get("filename");      // myFile.txt
string path = Request.QueryString.Get("path");              // @"\mydir\";
string fullPath;
fullPath = System.IO.Path.GetFullPath(path);
fullPath = System.IO.Path.GetFullPath(fileName);


Does the code validate URLs?

The application should not contain code similar to the following example.

Uri siteUri = new Uri("http://www.contoso.com/");
// use custom ways of verifying if the uri is absolute
 

Instead, the application should contain code similar to the following.

Uri siteUri = new Uri("http://www.contoso.com/");
//use the .NET Framework Library's IsAbsoluteUri() method
if (siteUri.IsAbsoluteUri())
    //take appropriate action


Does the code use MapPath?

Review code for the use of MapPath. MapPath should be used to map the virtual path in the requested URL to a physical path on the server to ensure that cross-application mapping is not allowed.

The application should not contain code similar to the following example.

string mappedPath = Request.MapPath( inputPath.Text, 
                                      Request.ApplicationPath);
 

Instead, the application should contain code similar to the following.

try
{
 string mappedPath = Request.MapPath( inputPath.Text, 
                                      Request.ApplicationPath, false);
}
catch (HttpException)
{
 // Cross application mapping attempted.
}
Personal tools