Protect Your ASP.NET App From SQL Parameter Injection

Securing your ASP.NET web app from SQL Injection attacks paramount in the design of any ASP.NET app. Say you are viewing a transaction of customer #448, andyour URL looks something like www.myapplication.com/customer.aspx?customerID=448. What is to stop customer 448 from typing in 449,  and viewing another customer’s transaction details? The situation can even escalate into typing in complete SQL statements and executing them inside the original statements you have coded.  Checking for let’s say a customer sessionID and matching it against the URL and the page will still have to be done by the app developer. This article will demonstrates a simple method of protecting against SQL Injection attacks by checking  for valid parameters in an existing ASP.NET application which can be used in any website. The main idea behind this technique is very simple and includes three components.

The Validation Class
This class contains static methods to check for valid values. For example, if you are expecting a string that is twenty characters long,it can check it for you and notify the application every time itencounters an invalid string on any page. There are several methods implemented in the example code. However, you can add your own and customize them to your needs.

Web.config
This is the file where you keep all of your application keys. So for example, if we would like to check for a customerID and make sure it is an integer, we would add a key named <safeParameters> and set its value to orderID-int32. Now every time our application will encounter an orderID parameter it will automatically check to see if it has a valid integer value.

Global.asax
This file will contain a utility method to match all of our known parameter types to their value. This method will be called isValidParameter. Every time a page is being requested, this method will be executed and will then notify the application if the parameteris valid.

The idea behind these three components working together to prevent SQL Injection attacks  is very simple: prepare all your utility methods to check for valid parameters, define all your valid parameters and check for valid values on each page, take into consideration that if you are using a customerID in twenty pages on your application, they all must be of an integer value. Plugging these components into your application is fairly simple and will ensure that an already   running website will prompt you every time a hacker tries to change a query string regardless of whether your programmers have checked for valid parameters or not. Bear in mind that this is a plug-in, and like all plug-ins it will take its toll on your application performance. A truely secure application will embed any security methods inside the page object only using utility classes to assist. However, if invalid parameters are a problem for you, then this is a good solution.

How to Implement the Example:

Step 1: Add a new utility class and copy and paste the code in parameterCheck.cs into it. Do not forget to change the namespace to fit the needs of the application.

 public class parameterCheck{
public static bool isEmail(string emailString){
return System.Text.RegularExpressions.Regex.IsMatch(emailString,
"['\w_-]+(\.['\w_-]+)*@['\w_-]+(\.['\w_-]+)*\.[a-zA-Z]{2,4}");
}
public static bool isUSZip(string zipString){
return System.Text.RegularExpressions.Regex.IsMatch(zipString ,"^(\d{5}-\d{4})|(\d{5})$");
}
}

Step 2: In the Web.config file, add a key under the <appSettings> tag. This key will contain all of the parameters you wish to check for and the types they need to be. The name of the key is <safeParameters>, and the value can be for example: ordered-int32,customerEmail-email.

<appSettings>
<add key="safeParameters" value="OrderID-int32,CustomerEmail-email,ShippingZipcode-USzip" />
</appSettings>

Step 3: In your Global.asax copy and paste the code in the example into your Application_BeginRequest method.

Continues…

ASP.NET Security Tutorial

Securing an ASP.NET application is paramount for any project. Here (in no particular order), in this tutorial we present the primary ASP.NET security best practices:

  • Ensure system patches are fully up-to-date
    Not really an ASP.NET specific best practice but since ASP.NET relies on the underling OS for its operation it is essential to ensure the OS to fully patched with the latest security updates.
  • Secure all connection strings
    Typically an app’s database will stored its most sensitive data so preventing unauthorized reading of the connection string is a must. The connection string should be stored in the web.config file and not in the code behind for pages and also not in the SqlDataSource control or other data source controls. For maximum security encrypt sensitive settings in config files – see Encrypt Connection Strings in ASP.NET for details.
  • Use parameterized queries or stored procedures instead of creating SQL commands by concatenating strings.
    It is possible to generate   the SQL for a command by building strings like below:

    SQLCmdStr = "Select * from users where username =' " & usernameTxt.Text  & "'

    This however allows for the possibility of SQL injection attacks by users directly typing SQL commands into text boxes which are then executed. Instead you can use a parameterized query as below:

    SQLCmdStr = “Select * from Users where Lastname =@LastName”
    SQLCmd.Parameters.Add(New SQLParameter(“@LastName”, ddl.SelectedItem.text))
  • Encrypt any sensitive data stored in View State
    View State is sometimes used to stored sensitive data sure as user names or even account numbers. Since View State is posted back to the server on every postback this data could be intercepted and read, therefore when any sensitive data is stored in View State the the page’s ViewStateEncryptionMode property should be set to true.
  • User input validation
    Always validate user input on the server even if it has been validated on the client since a user can easily bypass most client side validation by turning off javascript. The below code shows how to use Regex on the server-side to valid input:
  • using System.Text.RegularExpressions ;
    
    // Instance method:
    Regex regObj = new Regex(@"^[a-zA-Z'.\s]{1,40}$");
    Response.Write(regObj.IsMatch(Request.QueryString["InputName"]));
    
    // Static method:
    if (!Regex.IsMatch(Request.QueryString["InputName"],@"^[a-zA-Z'.\s]{1,40}$"))
    {
       // Name does not match expression
    }

    Note that user input does not only come from values input by the user on a form on the page. ASP.NET apps also take data form QueryStrings and cookies, these must also be validated in the same manner as input data.

    Continues…

ASP.NET ViewState Security

ASP.NET ViewState data is stored in a single Base64-encoded string  such as  this:

id="__VIEWSTATE" value="dDw3NDg2NdTI5MDg7Ozr4="/>

Since this value is not formatted in clear text, developers sometimes assume that their ViewState data is encrypted which is most certainly not the case. This data string can be reverse-engineered this and then viewed. This is an obvious security issue if sensitive data is being stored in ViewState.

To make ViewState secure, there are two choices, hash codes and ViewState encryption.

Use a hash code.

A hash code  is a cryptographically strong checksum. When you use a has code, ASP.NET calculates the checksum based on the current ViewState content data and then adds this to the hidden input field when the page  when is returned to the client.  On the page post back, ASP.NET then recalculates the checksum to  ensures a  match. If a malicious user were to  change the ViewState data, ASP.NET can detect the  the change reject the postback.
Hash codes are enabled by default,  however, sometimes developers elect  to disable hash codes to prevent problems on a web farm when  servers have different keys. Hash codes can be disabled on the page in the .aspx file’s Page directive:

<%@ Page EnableViewStateMac="false" ... %>

To disable hashing site-wide use the  ViewStateMac attribute of the pages  element in  web.config :

<configuration>
<system.web>
<pages enableViewStateMac="false" />
...
</system.web>
</configuration>

For more on hashing, please refer to C# Security – Hashing

Use ViewState Encryption.

Hash codes help to prevent ViewState data from being tampered with but they do not provide much assistance in preventing ViewState data from being read since hash codes can still be converted to clear text. To prevent ViewState being read, use the  ViewState Encryption, which can be turned on at the page level using the ViewStateEncryptionMode property of the Page directive:

<%@Page ViewStateEncryptionMode=”Always” … %>

Or site-wide in the web.config file:

<pages viewStateEncryptionMode=”Always” />

There are three settings for viewStateEncryptionMode:

  1. Always : All ViewState data is encrypted.
  2. Never : No ViewState data is encrypted.
  3. Auto : Data is only encrypted when specifically requested by the ASP.NET control.

The default setting is Auto so no data will be encrypted unless otherwise requested by a control on a page. For a control to request encryption in needs to call the Page.RegisterRequiresViewStateEncryption() method before it is rendered to HTML.

Note that using encryption incurs a performance penalty so it should only be used when necessary.

ASP.NET Security Best Practices

Security is one of the most important concerns in application software development. Building a robust security model is one of the most important factors that drive the success of application software. As far as security in ASP.NET is concerned, three terms come into my mind, i.e., Authentication, Authorization and Impersonation. Put simply, authentication authenticates the user’s credentials and authorization relates to the resources that an authenticated user has access to. This article is the first in a series of articles on ASP.NET security and discusses these concepts and their applicability.

Let us start our discussion with a brief outline on the sequence of events are as far as authentication and authorization are concerned when a new request comes in. When a new request arrives at IIS, it first checks the validity of the incoming request. If the authentication mode is anonymous (default) then the request is authenticated automatically. But if the authentication mode is overridden in the web.config file settings, IIS performs the specified authentication check before the request is passed on to ASP.NET.

ASP.NET then checks whether Impersonation is enabled or not. We will discuss impersonation later in this article. If impersonation is enabled, ASP.NET executes with the identity of the entity on behalf of which it is performing the task; otherwise, the application executes with the identity of the IIS local machine and the privileges of the ASP.NET user account. Finally, the ASP.NET engine performs an authorization check on the resources requested by the authenticated user and if the user is authorized, it returns the request through IIS pipeline.

The following section discusses Authentication, Authorization and Impersonation and how we can implement them in ASP.NET applications.
Authentication

Authentication determines whether a user is valid or not based on the user’s credentials. Note that a user can be authorized to access the resources provided the user is an authenticated user. The application’s web.config file contains all of the configuration settings for an ASP.NET application. An authentication provider is used to prove the identity of the users in a system. There are three ways to authenticate a user in ASP.NET:

  • Forms authentication
  • Windows authentication
  • Passport authentication

Forms Authentication

This is based on cookies where the user name and the password are stored either in a text file or a database. It supports both session and persistent cookies.

After a user is authenticated, the user’s credentials are stored in a cookie for use in that session. When the user has not logged in and requests for a page that is secured, he or she is redirected to the login page of the application. The following code snippet illustrates how this can be implemented in ASP.NET.

<configuration>
<system.web>
<authentication mode="Forms"/>
<forms name="LoginForm" loginUrl="LoginForm.aspx" />
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>

Note that the symbol “?” indicates all Non Authenticated and Anonymous users. Typically, the user enters the username and the password, clicks the login button and the form validates the values against values from that stored in a persistent store, usually a database. The following code snippet illustrates how this can be validated.

String username = txtUserName.Text;
String password = txtPassword.Text;
bool isUserValid = false;
//Code to validate the user name and password
if(isUserValid)
{
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, False);
else // User is not valid
lblMessage.Text = “Invalid login…”;
}

The RedirectFromLoginPage method creates an authentication ticket and is used to redirect an authenticated user back to the originally requested URL or the default URL. The following code snippet illustrates how we can specify the user’s credentials in the application’s web.config file.

<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="LoginForm.aspx">
<credentialspasswordFormat="Clear">
<user name="JoydipK" password="JudeK" />
</credentials>
</forms>
</authentication>
<authorization>
</system.web>
</configuration>

However you choose the above technique of authentication you should provide a means of encrypting the configuration file for security reasons. I will discuss these and other issues in the forthcoming articles in this series of articles on ASP.NET Security.

Continues…

Using Parameterized Queries in ASP.Net

There are two compelling reasons everyone should learn about Parameterized Queries. One entails one keyboard character and is more of a hassle reliever than anything else. That character, in code, can become either of two different objects, the single quote and the apostrophe. When you’re coding, either one can make your life truely miserable at times. The second, and MOST compelling reason to learn Parameterized Queries is to protect your database from SQL Injection Injection Attacks. If you have never heard of them, youneed to hear about them now. These attacks can reak havoc on your server and, more importantly, your data. Check out these articles on SQL Injection Attacks:
http://msdn.microsoft.com/msdnmag/issues/04/09/SQLInjection/
http://www.tech-faq.com/sql-injection-attack.shtml
Protecting Your ASP.NET from SQL Injection attacks
Simply by using Parameterized Queries, this becomes a first line of defense, and SQL Injection attacks are stopped in their tracks.

Anyone who has ever put together a long, involved SQL statement with variables, juggling single quotes, along with the double quotes (Tutorial on Single and Double Quotes), will tell you that it’s not much fun. And – on top of that, when we then talk about the apostrophe, it gets even more complicated.

Continues…