Security And Validations In .NET

Introduction

 
Validations in any application are so critical nowadays that developers ought to be on their toes while developing any such critical and sensitive application. Hackers are now in every corner of society, avoid them restrict them to post nonsense data into your applications. The attacks are so vulnerable that a security guard of any application is mandatory.
 
image
 
The security checks and implementations should be alert and active in the application to counter the attacks. Let's start learning about the different types of validations we can have in our MVC application.
 

Server-Side Validation

 
Let's begin with simple server-side validations. Server-side validation is required when we post something to the server with an expectation for the response, usually while posting form data. The form data post is generally very vulnerable. The attacks are quite easier for the attacker here. Thus, we need to check on the server if we are receiving valid data or not on our end. Thus, server-side validation to some extent can prevent nonsense input data. Let us discuss how to do validation explicitly using the view model. Let's discuss how: Explicitly means, we would be checking on server side after form post by the user, if the data input is valid input or not, then we post back the user with the validation message as a response. Suppose we have a model for the Registration of a user to an application. The model goes as the following:
  1. public class RegistrationViewModel(){  
  2.    public string FirstName { getset; }  
  3.    public string LastName { getset; }  
  4.    public string Address1 { getset; }  
  5.    public string Address2 { getset; }  
  6.    public string TelNo { getset; }  
  7. }  
Thus in the view/UI user will be displayed with the above labels and respective text boxes for input. The razor engine view page in the application looks like the following:
  1. @  
  2. model ServerSideValidationDemo.Models.RegistrationViewModel@ {  
  3.     ViewBag.Title = "Registration Page";  
  4. }  
  5.   
  6. @  
  7. using(Html.BeginForm()) {   
  8.   
  9.     @  
  10.     Html.LabelFor(m => m.FirstName)@ Html.TextBoxFor(m => m.FirstName, new {  
  11.         maxlength = 50  
  12.     })@ Html.ValidationMessageFor(m => m.FirstName)  
  13.   
  14.     @ Html.LabelFor(m => m.LastName)@ Html.PasswordFor(m => m.LastName, new {  
  15.         maxlength = 50  
  16.     })@ Html.ValidationMessageFor(m => m.LastName)  
  17.   
  18.     @ Html.LabelFor(m => m.Address1)@ Html.PasswordFor(m => m.Address1, new {  
  19.         maxlength = 50  
  20.     })@ Html.ValidationMessageFor(m => m.Address1)  
  21.   
  22.     @ Html.LabelFor(m => m.Address2)@ Html.TextAreaFor(m => m.Address2, new {  
  23.         maxlength = 200  
  24.     })@ Html.ValidationMessageFor(m => m.Address2)  
  25.   
  26.     @ Html.LabelFor(m => m.TelNo)@ Html.TextBoxFor(m => m.MobileNo, new {  
  27.         maxlength = 10  
  28.     })@ Html.ValidationMessageFor(m => m.MobileNo)  
  29.   
  30.  
  31. }  
  32.   
  33. //Thus, the above snippet would bring the user the UI where the users would post their input and click submit. In the razor view page, you can see the HTML Helper ValidationMessageFor.This helper displays the Validation message returned after validation from the server as a response, at the respective model property.Like For example, we want the user to enter the Model property First name as mandatory, then after validation, the helper would display the validation message beside the First Name Text Box. Now let's have a look at the Action snippet to which the post would call after Submit click. 
  34. [HttpPost]  
  35. public ActionResult UserRegistration(RegistrationViewModel registerModel) {  
  36.     if (string.IsNullOrEmpty(registerModel.FirstName)) {  
  37.         ModelState.AddModelError("FirstName""Please enter your first name");  
  38.     }  
  39.     if (!string.IsNullOrEmpty(registerModel.TelNo)) {  
  40.         Regex telNoRegex = new Regex("^9\d{9}$");  
  41.         if (!telNoRegex.IsMatch(registerModel.TelNo))  
  42.             ModelState.AddModelError("TelNo""Please enter correct format of Telephone Number");  
  43.     }  
  44.     if (ModelState.IsValid) {  
  45.         return View("Sucess"); //Returns user to success page  
  46.     } else {  
  47.         return View(); //Returns user to the same page back again  
  48.     }  
  49. }  
Thus, the above snippet would bring the user to the UI where the users would post their input and click submit. On the razor view page, you can see the HTML Helper ValidationMessageFor. This helper displays the validation message returned after validation from the server as a response, at the respective model property. For example, we want the user to enter the Model property First name as mandatory, then after validation, the helper would display the validation message beside the First Name Text Box. Now let's have a look at the Action snippet to which the post would call after Submit click.
  1. [HttpPost]  
  2. public ActionResult UserRegistration(RegistrationViewModel registerModel) {  
  3.     if (string.IsNullOrEmpty(registerModel.FirstName)) {  
  4.         ModelState.AddModelError("FirstName""Please enter your first name");  
  5.     }  
  6.     if (!string.IsNullOrEmpty(registerModel.TelNo)) {  
  7.         Regex telNoRegex = new Regex("^9\d{9}$");  
  8.         if (!telNoRegex.IsMatch(registerModel.TelNo))  
  9.             ModelState.AddModelError("TelNo""Please enter correct format of Telephone Number");  
  10.     }  
  11.     if (ModelState.IsValid) {  
  12.         return View("Sucess"); //Returns user to success page  
  13.     } else {  
  14.         return View(); //Returns user to the same page back again  
  15.     }  
  16. }  
Before explaining the above snippet, let's understand how this will be called after Submit click. @using (Html.BeginForm()), this does the trick even without specifying the Action and controller. This actually internally calls the Post method of the current url, i.e. looks for the HttpPost attribute to the respective action name of the current url. Thus, in this way, the post method of UserRegistration gets called and this also posts the required view model to the action, fetching the values input by the user. After the Action Result method gets called, there is a check for the properties explicitly. Here, we check if the user has input into the First name or not. If the user skipped the First Name textbox and submits, then we post the user with the validation message saying "Please enter the first name". This validation check will not let the user post the input unless he adds the first name. Similarly, the telephone number is also validated with the regular expression (for the Indian telephone number) given. This was all about the validation being done explicitly. Now, since we are developing an MVC application, it provides pre-defined attributes which can be used to validate our post data. The attributes are called Data-Annotations attribute. Let's look at their usages below: The use of data annotations can be extensively done in order to avoid having the controller post action, explicitly checking for each property. The data annotations attribute in a view model will look like the following:
  1. public class RegistrationViewModel() {  
  2.     [Required]  
  3.     [Display(Name = "First name")]  
  4.     [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]  
  5.     public string FirstName {  
  6.         get;  
  7.         set;  
  8.     }  
  9.     public string LastName {  
  10.         get;  
  11.         set;  
  12.     }  
  13.     public string Address1 {  
  14.         get;  
  15.         set;  
  16.     }  
  17.     public string Address2 {  
  18.         get;  
  19.         set;  
  20.     }  
  21.     [Required(ErrorMessage = "Please Enter Telephone Number")]  
  22.     [Display(Name = "Tele Phone")]  
  23.     [RegularExpression("" ^ 9\ d {  
  24.             9  
  25.         }  
  26.         $ "", ErrorMessage = "Please Enter Correct format of Telephone No.")]  
  27.     public string TelNo {  
  28.         get;  
  29.         set;  
  30.     }  
  31. }  
The view model above uses Data Annotations attributes and all the required validations for the properties are provided. Let's discuss one by one:
  1. Required: This attribute forces the user to enter the value for that specific property and then submit the form, else displays "The FirstName is required". Mark here, the previous message would be a default error message whereas, for the telephone number, the custom error message would be displayed.
  2.  
  3. Display(Name = ): This attribute sets the label for the model property. We just need to specify @Html.LabelFor(m=>m.TeleNo). This would display the specified custom label for the property, here it would display TelePhone.
  4.  
  5. RegularExpression: This attribute is very handy especially when we have properties such as Email Address, TelePhone Numbers, and specific expressions for passwords in the forms. We just specify the expression in the attribute and it validates the input from a user and states if it is valid or else displays the error message.
Thus, here the view page would go like the same as above. And when we submit, the action post method called would be different i.e. much less code. Let's have a look at the following action:
  1. [HttpPost]  
  2. public ActionResult UserRegistration(RegistrationViewModel registerModel){  
  3. if (ModelState.IsValid)  
  4.    {  
  5.       return View("Success");//Return to the success   
  6.    }  
  7.    else  
  8.    {  
  9.       return View();//Return back to the same view   
  10. }  
  11. }   
Thus, the data annotations here made it so simple and easy. Here comes another security vulnerability, i.e. Cross-Site Request Forgery Attacks, which can be easily attacked using the simple Fiddler. When we post any data, we can easily manipulate the data posted by one user using the fiddler and damp into the application and even ruin it. This is indeed very dangerous. Let's see how to prevent cross-site forgery attacks.
 
Preventing Cross-Site Forgery Attacks
 
In MVC applications, while posting the form data, it is quite simple to prevent such requests if understood properly. MVC provides the attribute [ValidatAntiForgeryToken] on the respective action. Let's see the flow in the snippet first. First, we need to place the AntiForgeryToken helper in the razor view page like the following:
  1. @using(Html.Form("UserRegistration""Register")) {   
  2.    @Html.AntiForgeryToken()   
  3.    //Then here normal rest form as mentioned above   
  4. }  
Then in the controller "Register" for the action "UserRegistration"(POST) add the attribute as in the following code snippet:
  1. [HttpPost]  
  2. [ValidateAntiForgeryToken]  
  3. public ActionResult UserRegistration(RegistrationViewModel registerModel){  
  4.    //ModeState Valid check and rest code goes here  
  5. }  
So we have seen what two simple steps we need to do. Now let's understand how it does. What happens exactly when we do not place these attributes. How vulnerable our controller is and to what extent an attacker can affect the application. Suppose we are on an Edit page, where a user sought to edit a few of his login information. Now an attacker from over a third party domain hosts a simple HTML that would post some information to the same Edit action, the user was to. Then, somehow the user if navigates to the Html page set up by the attacker, the user unknowingly is posting unwanted data to the server and normal saving to the database. Here the attacker may be replacing the email ids or any other vulnerable information with his own and retrieving the user's data. BOOM! This is a crash, rather a crap! Thus, what we need to do here, we need to check if the request to the server action is coming from the same domain, the user has logged in. For this, we need to have some header or property which will be mapped when a request is made, and if matches then post else let the authentication fail. This is actually what the attribute does. The ValidateAntiForgeryToken actually sets a cookie to the incoming request called __RequestVerificationToken, and the same __ This validation check will not let the user post the input unless he adds the first name. Similarly, the telephone number is also validated with the regular expression (for the Indian telephone number) given. This was all about the validation being done explicitly. Now, since we are developing an MVC application, it provides pre-defined attributes which can be used to validate our post data. The attributes are called Data-Annotations attribute. Let's look at their usages below: The use of data annotations can be extensively done in order to avoid heaving the controller post action, explicitly checking for each property. 
 
Another concept that is vulnerable to such attacks and may breach the security in the application is SQL Injection. Let's discuss this in brief.
 

SQL Injection Attacks & Prevention Techniques

 
What exactly is an SQL Injection attack? SQL Injection is an attack to fool and manipulate the application database. This is done through the malicious input from the user during post methods and if the posted data is not validated before being executed as SQL query. This is really very dangerous which can let attackers get all the sensitive data or even delete the records from all the tables, truncating them, just by posting a simple query to drop instead of actual data. In this, the objective of the attacker is to post their query into the application and let the server run and give him the response if not handled at the server end. Let's see how: Suppose we have a SQL query to select the names of houses and display them. The query is:
  1. var sqlTobeExecuted = "SELECT HouseID, HouseName"+  
  2. "FROM House " +  
  3. "WHERE Address LIKE '" + searchInputParam +"%';  
  4. SqlDataAdapter da = new SqlDataAdapter(sqlTobeExecuted , DbCommand);  
The above query is not parameterized and is a simple query in string format to get the house details. Now suppose the attacker posts the searchInputParam (which originally comes from the textbox input of the user) as:
 
' UNION SELECT id,name FROM sysobjects;--
 
Mark the statement what becomes after that is passed to the string query,
 
SELECT HouseID, HouseName FROM House WHERE Address LIKE '' UNION SELECT id,name FROM sysobjects;--%'
 
The first apostrophe in the searchInputParam closes the Like parameter in the SQL query and the double dashes "--" comment out the rest of the query. That gives the list of all the HouseNames and also all the tables present in the database. Even they can also get the ids of the sysObjects and use the Ids to retrieve the column names of the database table they want. Suppose there is a table named Users. Obviously, the table would have all the user details. Thus, with the id and the table name the attacker can retrieve the column names of the Users table using the following query:
 
' UNION SELECT name FROM syscolumns WHERE id = "USERID";--
 
Thus the complete database can be exposed to malicious users with a single click. To prevent this,
  • Encrypt essential and sensitive data like passwords, credit card information, and other details. So that to some extent if by anyhow they get the details they cannot decrypt it. Use one-way hashing to encrypt the record data.
  •  
  • Using parameterized queries instead of strings, in order to avoid directly injecting the values from the User input to the query as we saw in the above section. A parameterized query would prevent the malicious input and it would look like below:
    1. var commandToBeExecuted = "SELECT HouseID, HouseName FROM House"+  
    2. "WHERE Address Like @Address";  
    3. SqlCommand cmd = new SqlCommand(commandToBeExecuted , conn);  
    4. cmd.Parameters.Add("@Address",address);  
    As we see in the preceding query we avoid passing directly the string input, instead, we are using parameters into the SQL query that would prevent such attacks.
  •  
  • Use of parameterized Stored Procedures, which also prevent and prove to be a good solution to these malicious attacks of injection. Also, it is advisable to not trust them completely/blindly, so it is always better to check for the sensitive data from user inputs and then execute the Stored procedure. This can be done, where the developer can think there are chances of vulnerability.
  •  
  • Entity Framework & LINQ, it is interesting to note here is while using LINQ to an entity, the query generation does not use the string-based approach, rather it uses the object model API, thus being not susceptible to SQL injection attacks.

Authentication & Authorization

 
These two are very important in any application and are two different concepts altogether but are used to solve the same thing i.e. Security. When we develop a secure application, login is highly essential. Thus, properly authenticating users to the application & authorizing users to a particular section of the application is challenging. Usually, Forms Authentication is implemented across MVC applications. In the web.config file, the following configuration is set.
 
Only this will not set the authentication. You need more setup to be done. This would involve a lot of configuration. WebSecurity in MVC makes it easy and secure to be implemented. It provides tables and hashing as well. The hashing it provides is one way and very secure. You can learn more about implementing Web Security in MVC from Web Security in MVC. Thus after setting this authentication, the essential thing is Authorization that can be provided on controller level, action level, which can be customized in order to check for the access levels along with the sessions. Only Authorize attribute will let the check for the session, we customize it to check for the roles and access levels for the screens as well.
  1. [Authorize]  
  2. public class HomeController : Controller  
  3. {  
  4.    public ActionResult Index()  
  5.    {  
  6.       return View();  
  7.    }  
  8. }  
In the above snippet, the entire controller has been authorized. That is each method inside the controller will be first authorized.
  1. public class HomeController : Controller  
  2. {  
  3.    public ActionResult Index()  
  4.    {  
  5.       return View();  
  6.    }  
  7.    [Authorize]  
  8.    public ActionResult GetHome(){  
  9.       return View()  
  10.    }  
  11. }  
Here, only the action method GetHome is authorized, not the whole controller. Thus, Authentication and Authorization are very important factors that ought to be taken into consideration.
 
More security considerations in MVC
 
Straight from the OWASP security points, it is advisable to hide the MVC versions as well as ASP.NET versions we use, never expose the versions through the headers.
 
X-AspNet-Version 4.0.30319 X-AspNetMvc-Version 5.0
 
We need to hide the versions which appear in the Network tab of the developer table. Let's know how to remove the versions of ASP.NET and ASP.NET MVC from the headers.
  • ASP.NET Version: To hide the X version of ASP.NET we use the following Web.Config change.
     
    The above will hide the ASP.NET versions.
     
  • ASP.NET MVC Versions: To hide the X version of the ASP.NET MVC we use the following change in the Application_Start method of the Global.asax. The snippet will be like the following:
    1. protected void Application_Start()  
    2. {  
    3.    MvcHandler.DisableMvcResponseHeader = true;  
    This hides the ASP.NET MVC version from the headers in the Network tab.
     
  • Lastly, there are chances of exposing the users to the Yellow screen of death, when an exception occurs in the application and is unhandled. Thus, it is advisable to have a custom error page, where users will be landing when exceptions occur. Let's see how: Custom errors in the Web config need to be on. There are three modes of Custom errors. They are:
     
    1. On: Prevents the stack trace that is shown when exceptions arise --Also allows displaying custom error pages to the end user --Custom error pages shown to both Remote Clients as well as Local.
    2.  
    3. Off: Makes the end-user view the description of the exception along with the entire stack trace. --ASP.NET error/exception and stack trace is shown to both Remote clients and Local as well.
    4.  
    5. Remote only: This is the best among all for the developers’ perspective, as this allows the Remote clients to view the custom error messages/pages. It allows the local users especially developers to view the ASP.NET errors and this is the default value.
The other attribute which is used for the custom error element is defaultredirect. This is used to redirect the users to a default page when exceptions occur.
 
The exceptions can also be handled globally at the application level by using the following code snippet:
  1. protected void Application_Error(Object sender, EventArgs e)  
  2. {  
  3.    Exception ex = Server.GetLastError(); //self explanatory gets the most recent error  
  4.    Server.ClearError(); //self explanatory clears the error   
  5.    //(Required to clear as otherwise user gets to see the default ASP.NET error handlers)  
  6.    Response.Redirect(""); //default redirect.   
  7. }  
For details, you can follow Custom Errors.
 

Conclusion

 
Thus, security and validations are very important features to be implemented in any application nowadays. According to Forbes, in a day 30,000 sites were hacked. This is truly an astonishing number. And in today's world, most of the sensitive information is being stored in the cloud. Thus, in any application, the data have a great chance of being exposed and hacked. So security is a major concern and needs to be handled very carefully. Hopefully, some of the major points are discussed above and can be implemented in any application to avoid any sort of breach. CodeProject.
 
References
 
How can I miss the references from which I learned and got this opportunity to share with the world? OWASP Cheat Sheet Security testing SQL Injection and Entity Framework.


Invincix Solutions Private limited
Every INVINCIAN will keep their feet grounded, to ensure, your head is in the cloud