Click here to Skip to main content
13,195,379 members (66,889 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

81.8K views
1.5K downloads
130 bookmarked
Posted 3 Aug 2016

10 Points to Secure Your ASP.NET MVC Applications.

, 4 Aug 2016
Rate this:
Please Sign up or sign in to vote.
In this article we will run through 10 points which will help us to make our MVC code secure.

Contents

Introduction

1) Security Misconfiguration (Error Handling Must Setup Custom Error Page)

2) Cross-Site Request Forgery (CSRF)

3) Cross-Site Scripting (XSS) attacks

4) Malicious File Upload.

5) Version Discloser

6) SQL Injection Attack.

7) Sensitive Data Exposure

8) Audit trail

9) Broken authentication and session management

10) Unvalidated Redirects and Forwards

Introduction

Lot of ASP.NET MVC developers are great in delivery , writing high performance code and so on. But when it comes to security there is no planning done. So in this article we will run through 10 points which will help us to make our MVC code secure.

In case you are new to MVC I would suggest to start from this youtube tutorial :-

1) Security Misconfiguration (Error Handling Must Setup Custom Error Page)

In this kind of attack the attacker intercepts form data which is submitted by end User and changes values and sends the modified data to the server.

So for such kind of scenarios developers do put proper validations in place but when these validations display error lot of information of the server is revealed.

So let us demonstrate the same practically.

Example:-

For showing demo I have created an Employee form which takes basic Employee details.

Fig 1.Add Employee form View in the browser along with Markup.

EmployeeDetailModel View.

Fig 2.EmployeeDetail Model.

So is data annotation validations more than enough to secure the page. No, that’s not enough for securing page I will show you as mall demo of how these validations get bypassed.

In case you are new to validation using Data annotation please do watch this youtube https://www.youtube.com/watch?v=Gft64NdIx3k which explains how to use data annotations for validation purpose.

Below snapshot shows that address field is validating it ask for only 50 characters.

Fig 3.After adding validation to Model now we are validating form you can see Address input field which only accepting 50 characters it is not accepting more than 50 characters it showing Error and message .

Intercepting Add Employee View

Now let’s intercept this form and then submit to the server from the intercept. I am using a tool called as burp suit which catches you request which is going to the server and coming from the server.

In the below snapshot I have caught a request which is going to theserver.

Fig 4.Intercepting Add Employee form using burp suite you can view that if theusersubmits theform then it catches data in this tool.

In the below snapshot the request which I have caught is going to theserver. You can see i have changed Address which is only taking 50 I have added more than 50 characters and then submitted to theserver.

Intercepted Address field of Add Employee form

Fig 5.Intercepted Address field in burp suite and submitted to theserver.

Below is the snapshot which shows the request which is submitted to theserver which has more than 50 characters.

Debugging mode of Employee form

After submitting more than 50 characters to the Address fields the server throws exception.Because in the databasethe data type of Address field isvarchar(50) and the data is more than 50 so an exception is but obvious.

Fig 6.Intercepted Address field in burp suite and submitted to theserver.

Fig 7.Interception of Address field caused an error.

Problem with displaying Error occurred to users

Now exception which occurs is directly displayed to attacker which leak lots of valuable information about the server and our program behavior. Using this error information he can try various permutation and combination to exploit oursystem.

Fig 8 :- Displaying Error directly to Users.

Solution: -

So the solution here is we need to set some kind of error page which does not show the internal technical error but rather shows a custom error message.

We have two approaches for it :-

  1. Create a custom Error handling Attribute.
  2. Setting Custom Error page from Web.config file

Solution 1:-

Create a custom Error handling Attribute using HandleErrorAttribute or using IExceptionFilterFilter

Showing example using HandleErrorAttribute

using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Web.Mvc;

namespaceMvcSecurity.Filters
{
publicclassCustomErrorHandler : HandleErrorAttribute
    {
publicoverridevoidOnException(ExceptionContextfilterContext)
        {
Exception e = filterContext.Exception;
filterContext.ExceptionHandled = true;
var result = newViewResult()
            {
ViewName = "Error"
            }; ;
result.ViewBag.Error = "Error Occur While Processing Your Request Please Check After Some Time";
filterContext.Result = result;     
        }
    }

After creating custom Error attribute we need to apply this globally for entire application. For doing this we need to call this attribute in FilterConfig class which is in App_Start Folder as show below.

usingMvcSecurity.Filters;
usingSystem.Web;
usingSystem.Web.Mvc;

namespaceMvcSecurity
{
publicclassFilterConfig
    {
publicstaticvoidRegisterGlobalFilters(GlobalFilterCollection filters)
        {
filters.Add(newCustomErrorHandler());
        }
    }
}

Whenever error occurs the CustomErrorHandler attribute will get called and it will redirect toError.cshtml page. And any message you want to pass then you can pass through @ViewBag.Errorfrom CustomErrorHandler attribute.

Html Error Page code snippet

@{
    Layout = null;
}

<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width"/>
<title>Error</title>
</head>
<body>
<hgroup>Error.

@ViewBag.Error

 

</body> </html>

Error Page View

Fig 9.Displaying Custom Error page if any error occurs in Application.

Solution 2:-

  1. Setting Custom Error page fromWeb.configfile
  2. If you do not want to write attribute then you can set Custom Error page in Web.config file. Before doing that just create a simple Error page in HTML for displaying if any error occurs.

In Web.configfile there is system.webtag inside that add Custom error tag as show below.

 

Fig 10.Web.config File View while setting Custom Error page.

Html Error Page code snippet

<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width"/>
<title>Error</title>
</head>
<body>
<hgroup>Error.

An error occurred while processing your request...........

 

</body> </html>

Html Error Page View

Fig 11.Displaying Custom HTML Error page if any error occurs in Application.

Wow, we have just started Securing our web application. Let’s see the second point.

2) Cross-Site Request Forgery (CSRF)

A CSRF vulnerability allows an attacker to force a validated and logged in user to perform actions without their consent or unknowingly.

Take this simple example.

  • User logs in to the bank server.
  • Bank authorizes and a secure session is established between user and the bank server.
  • The attacker sends an email with a malicious link saying “Earn 100000$ now” to the user.
  • User clicks on the malicious link and the site tries transfer money from your account to the attackers account. Because the secure session is established the malicious code can execute successfully.

Microsoft has recognized this threat and for preventing the same we have something called as AntiForgeryToken.

Solution:-

We need to add @Html.AntiForgeryToken()helper in your form inside form tag . And on the Action Method which handles your post ([HttpPost])Request we need to put[ValidateAntiForgeryToken] attribute which will check if the token is valid.

Adding [AntiForgeryToken] helper to View

Fig 13.Adding AntiForgeryToken on View.

Adding [ValidateAntiForgeryToken] Attribute to HttpPost[HttpPost] Method.

Fig 14.Adding ValidateAntiForgeryTokenon [HttpPost] Method (Index).

WorkingofAntiForgeryToken

When we add AntiForgeryToken helper on View it creates a hidden field and assigns a unique token value to it and meanwhile a session Cookie is added to the browser.

When we post formHTML itschecksfor __RequestVerificationToken Hidden field and whether __RequestVerificationToken Cookie are present or not. If either the cookie or the form __RequestVerificationToken Hidden field values are missing, or the values don't match, ASP.NET MVC does not process the action. This is how we can prevent cross-site request forgery attack in asp.net MVC.

RequestVerificationTokenon View snapshot.

Fig 15.RequestVerificationToken generated the hidden field.

RequestVerificationToken Cookie snapshot.

Fig 16.RequestVerificationToken generated a cookie.

3) Cross-Site Scripting (XSS) attacks

Cross-site Scripting (XSS) is an attack in which malicious scripts is injected via input fields this attack is most common and allows an attacker to steal credentials and valuable data that can lead to a big security breach.

Fig 17. Cross Site Scripting (XSS).

In this attack attacker visits a website and tries to execute a malicious scripts in form comment box. Now if website has not checked for Malicious code then the code can get executed on the server causing damage.

Lets try to understand the same using a example.Below is simple Employee form which we are trying to save data. Now in the text box I am trying to execute some malicious code using javascript using the SCRIPT tag. But if we try to submit the same MVC throws an error that something bad is happening.

In short by default ASP.NET prevents Cross Site Script attack.

Understanding the Error Displayed

A potentially dangerous Request.Form value was detected from the client (worktype="<script>alert('hi');").

This error occurs because MVC is validating data which is entered by User and if User tried to execute such script it does not allow and that’s a good news.

Fig 18.SubmittingMaliciousscripts in Input fields which lead to Error.

But now what if we want to put SCRIPT tag. For example programming sites like codeproject has a genuine need that end user should submit code and script snippets. In those scenarios we would like the end user to post code through the UI.

So lets us understand how to do the same but at the same time not compromise on security.

So we have four things via which we can allow scripts to be posted.

Solution: -

  1. [ValidateInput(false)]
  2. [AllowHtml]
  3. [RegularExpressionAttribute]
  4. AntiXSS Library

Solution 1:-

ValidateInput

[ValidateInput] is an attribute which can be applied on Controller or Action Method on which we want the script to go through.

If we want Mark up to be allowed then we need to set enableValidation Properties to False([ValidateInput(false)]) which will not validate input if we set to true then[ValidateInput(true)]) It will validate input.In the same way, if you apply it on Controller then it appliesto entire action methods inside thecontroller and if you apply it on Action Method then it will only be specific to that action method.

But ValidateInputattributewill apply to all properties of Model (EmployeeDetails).

Snapshot of Applying ValidateInputAttributeon HttpPostMethod.

Fig 19.Applying ValidateInput Attribute on HttpPost Method.

Snapshot after Applying ValidateInputAttribute

Fig 20.After adding ValidateInput Attributeon HttpPost Method it allows submitting script.

Solution 2:-

AllowHtml

[AllowHtml]attributes that is applied to Model properties such that it will not validate that particular Model property on which AllowHtmlattribute is added.This allows submittingHTML for avoiding Cross Site Scripting attack.

In below snapshot, I have applied AllowHtmlattribute on Address property of EmployeeDetails Model.

Fig 21.Applying [AllowHtml] Attribute on Required Model Property.

After Applying AllowHtmlattribute on that Address Property now Address property will not validate and allow HTML to be submitted in this field.

Fig 22.After adding [AllowHtml] Attributeon Address Model Property it allows submitting script.

Solution 3:-

Regular Expression

The third solution to XSS attack is validating all your Fields with Regular Expression such that only valid data can move in.

Use Regular Expression to validate input to protect from XSS attack below is Snapshot.

Fig 23.Applying Regular Expression to Model Property.

List of Regular Expression to Use.

Alphabets and Space

[a-zA-Z ]+$

Alphabets

^[A-z]+$

Numbers

^[0-9]+$

Alphanumeric

^[a-zA-Z0-9]*$

Email

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

Mobile no.

^([7-9]{1})([0-9]{9})$

Date Format( mm/dd/yyyy | mm-dd-yyyy | mm.dd.yyyy)

/^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\\d\\d+$/

Website URL

^http(s)?://([\\w-]+.)+[\\w-]+(/[\\w- ./?%&=])?$

Credit Card Numbers

Visa

^4[0-9]{12}(?:[0-9]{3})?$

MasterCard

^5[1-5][0-9]{14}$

American Express

^3[47][0-9]{13}$

Decimal number

((\\d+)((\\.\\d{1,2})?))$

Solution 4:-

AntiXSS Library

The fourth solution to XSS attack is by using MicrosoftAntiXSSLibrary which will help to protect your application.

Now let’s start with install MicrosoftAntiXSSLibrary from NuGetjust right click on Project then select ManageNuGetPackages.

Fig 24.Choosing Manage NuGet Package for adding Package.

After selecting a new dialog will pop up with name ManageNuGetPackages in thisdialog search AntiXSSLibrary in thesearch box then choose the first option which is AntiXSS click on install button.

Fig 25.Adding Microsoft AntiXSS Library to Project.

Reference added after installing

Fig 26.After adding MicrosoftAntiXSS Library to Project.

After installing we are going to have a look on how to use AntiXSSLibrary.

Sanitizer Class

Fig 27. Sanitizer Class which we are going to use for sanitizes inputs.

Below snapshot shows how to use Sanitizer Class Method

Sanitizer is a static class we can access anywhere we just need to provide input which field which we need to validate to Sanitizer class method (GetSafeHtmlFragment) it will check and return you Sanitize string.

Fig 28.Here we are showing how to sanitize inputs usingSanitizer Class for that I have taken address field as input to sanitize.

We can use this Method to filter malicious scriptwhile saving in thedatabase and displaying in thebrowser.

Tip: - Use [ValidateInput(false)] or [AllowHtml] before using this AntiXSS library else it will throw error “A potentially dangerous Request.Form”

4) Malicious File Upload.

Till now we have learned how to protect all your input fields from attack but still, we are missing one main field it is File upload control we need to protect from taking invalid input most attackers try to upload a malicious file which may cause a security issue. The attacker can change file extension [tuto.exe to tuto.jpeg] and the malicious script can be uploaded as an image file. The Most of the developer just look on the file extension of the file and save in folder or database but file extension is valid not file it may have a malicious script.

Fig 29.This image shows how people try to upload files some try valid files and some invalid files.

Solution:-

  1. First thing we need to do is validate file uploads
  2. Allow only access to files extension which are required
  3. Check the file header.

First, thething I am going to add a file upload control on View.

Adding file upload control

Fig 30.Adding File upload control on Add employee View.

We have added File uploadcontrol on View next we are going validate file on Submit.

Validating file uploads on Index HttpPost Method

In this Method first, we are going to validateContent-Lengthof thefile if it is zero[upload.ContentLength == 0] then user has not uploaded file.

If Content-Lengthis greater than zero then it has file [upload.ContentLength> 0] and we are going to reading Filename of File along with Content Type and File Bytes.

[HttpPost]
   [ValidateAntiForgeryToken]
publicActionResult Index(EmployeeDetailEmployeeDetail)
   {
if (ModelState.IsValid)
       {
HttpPostedFileBase upload = Request.Files["upload"];
if (upload.ContentLength == 0)
           {
ModelState.AddModelError("File", "Please Upload your file");
           }
elseif (upload.ContentLength> 0)
           {
stringfileName = upload.FileName; // getting File Name

stringfileContentType = upload.ContentType; // getting ContentType

byte[]tempFileBytes= newbyte[upload.ContentLength]; // getting filebytes

var data = upload.InputStream.Read(tempFileBytes, 0, Convert.ToInt32(upload.ContentLength));

var types = MvcSecurity.Filters.FileUploadCheck.FileType.Image;  // Setting Image type

var result = FileUploadCheck.isValidFile(tempFileBytes, types, fileContentType); // Validate Header

if (result == true)
               {
intFileLength = 1024 * 1024 * 2; //FileLength 2 MB
if (upload.ContentLength>FileLength)
                   {
ModelState.AddModelError("File", "Maximum allowed size is: " + FileLength + " MB");
                   }
else
                   {
stringdemoAddress = Sanitizer.GetSafeHtmlFragment(EmployeeDetail.Address);
dbcon.EmployeeDetails.Add(EmployeeDetail);
dbcon.SaveChanges();
return View();
                   }
               }
           }
       }
return View(EmployeeDetail);
   }

Till now it was basic validation we have done let’s Validate file which is uploaded for doing that I have writtena static class with name FileUploadCheckin this class there are Various Method for validating different file type for now I am going to show you how to validate Images files and only allow image files only.

FileUploadCheck Class

Fig 31.View of FileUploadCheck Class which is custom created for validating File uploads.

In above snapshot there is ImageFileExtensionenum which contains Image formats and File types.

privateenumImageFileExtension
 {
none = 0,
jpg = 1,
jpeg = 2,
bmp = 3,
gif = 4,
png = 5
 }
publicenumFileType
 {
     Image = 1,
     Video = 2,
     PDF = 3,
     Text = 4,
     DOC = 5,
     DOCX = 6,
     PPT = 7,
 }

If it has passed basic validation thenwe are going to call isValidFileMethod which take bytes, File type, FileContentType as input.

publicstaticboolisValidFile(byte[] bytFile, FileTypeflType, StringFileContentType)
 {
boolisvalid = false;
if (flType == FileType.Image)
     {
isvalid = isValidImageFile(bytFile, FileContentType);//we are going call this method
     }
elseif (flType == FileType.Video)
     {
isvalid = isValidVideoFile(bytFile, FileContentType);
     }
elseif (flType == FileType.PDF)
     {
isvalid = isValidPDFFile(bytFile, FileContentType);
     }
returnisvalid;
 }

After calling isValidFilemethod it will call another static method based on File type.

If File type is image then it will call first Method [isValidImageFile] else File type is Video then second Method [isValidVideoFile] and in similar way if File type is PDF then last method [isValidPDFFile] will get called.

After completing with understanding isValidFileMethodlet’s have a look on [isValidImageFile] Method which will get called.

Below is complete code snippet of [isValidImageFile] Method.

In this Method, we are allowing limited Image file extensions [jpg, jpeg, png, bmp, gif]

Working of this isValidImageFilemethod

When we pass bytes and FileContentType to this method then it will first check for FileContentTypeon thebase of that it will set

ImageFileExtension

after that it is going to check header bytes which we have against uploaded file bytes if it matches that then File is valid [true] else file is invalid [false].

 

publicstaticboolisValidImageFile(byte[] bytFile, StringFileContentType)
   {
boolisvalid = false;

byte[] chkBytejpg = { 255, 216, 255, 224 };
byte[] chkBytebmp = { 66, 77 };
byte[] chkBytegif = { 71, 73, 70, 56 };
byte[] chkBytepng = { 137, 80, 78, 71 };


ImageFileExtensionimgfileExtn = ImageFileExtension.none;

if (FileContentType.Contains("jpg") | FileContentType.Contains("jpeg"))
       {
imgfileExtn = ImageFileExtension.jpg;
       }
elseif (FileContentType.Contains("png"))
       {
imgfileExtn = ImageFileExtension.png;
       }
elseif (FileContentType.Contains("bmp"))
       {
imgfileExtn = ImageFileExtension.bmp;
       }
elseif (FileContentType.Contains("gif"))
       {
imgfileExtn = ImageFileExtension.gif;
       }

if (imgfileExtn == ImageFileExtension.jpg || imgfileExtn == ImageFileExtension.jpeg)
       {
if (bytFile.Length>= 4)
           {
int j = 0;
for (Int32 i = 0; i <= 3; i++)
               {
if (bytFile[i] == chkBytejpg[i])
                   {
                       j = j + 1;
if (j == 3)
                       {
isvalid = true;
                       }
                   }
               }
           }
       }


if (imgfileExtn == ImageFileExtension.png)
       {
if (bytFile.Length>= 4)
           {
int j = 0;
for (Int32 i = 0; i <= 3; i++)
               {
if (bytFile[i] == chkBytepng[i])
                   {
                       j = j + 1;
if (j == 3)
                       {
isvalid = true;
                       }
                   }
               }
           }
       }


if (imgfileExtn == ImageFileExtension.bmp)
       {
if (bytFile.Length>= 4)
           {
int j = 0;
for (Int32 i = 0; i <= 1; i++)
               {
if (bytFile[i] == chkBytebmp[i])
                   {
                       j = j + 1;
if (j == 2)
                       {
isvalid = true;
                       }
                   }
               }
           }
       }

if (imgfileExtn == ImageFileExtension.gif)
       {
if (bytFile.Length>= 4)
           {
int j = 0;
for (Int32 i = 0; i <= 1; i++)
               {
if (bytFile[i] == chkBytegif[i])
                   {
                       j = j + 1;
if (j == 3)
                       {
isvalid = true;
                       }
                   }
               }
           }
       }

returnisvalid;
   }

Calling isValidFile method from Action Method

We are going to call (FileUploadCheck.isValidFile) Method and then we are going to pass Parameter File Bytes, Types, FileContentType.

This Method will return Boolean value if it is valid file then true else it will return false.

stringfileName = upload.FileName; // getting File Name

stringfileContentType = upload.ContentType; // getting ContentType

byte[] tempFileBytes = newbyte[upload.ContentLength]; // getting filebytes

var data = upload.InputStream.Read(tempFileBytes, 0, Convert.ToInt32(upload.ContentLength));

var types = MvcSecurity.Filters.FileUploadCheck.FileType.Image; // Setting Image type

var result = FileUploadCheck.isValidFile(tempFileBytes, types, fileContentType); //Calling isValidFile method

After understanding code snippet now let’s see ademo withhow it works.

Below snapshot shows an Employee form with file upload control.

We are going to fill below form and choosing a valid file.

Fig 32.Add Employee form View after adding file upload.

Choosing a valid .jpg file and check how it will validate in details

Choosing a .jpg image from disk.

Fig 33.Choosing File for upload.

Snapshot of Employee form after choosing a file.

In this part, we have chosen a file.

Fig 34.After Choosing File for upload.

Snapshot of debugging Index Post Action Method.

In this part we have posted an Employee form with a file here we can see have it is validating basic validations.

Fig 35.After Submitting Form for saving data, it shows real time value of file which we have uploaded.

Snapshot of debugging Index Post Action Method.

In this part, you can see thereal-time value of file which we have uploaded it has passed basic validation.

Fig 36.After Submitting Form for saving data, it shows real time value of file which we have uploaded.

Snapshot of FileUploadCheck Class while isVaildFile Method getsCalled.

In this part after calling isValidFile Method it going call another method according to its FileContentType.

Fig 37.Calling method inside FileUploadCheck Class according to File Type.

Snapshot of isVaildImageFile Method while checking Header Bytes.

In this method, it will check header bytes of theimage which is upload against the bytes which we have if it matches then it is a valid file else it is not avalid file.

Fig 38.Check header bytes of theimage which is upload against the bytes which we have.

5) Version Discloser

Version information can be used by anattacker to target specific attack on that Version which is disclosed.

Whenever browsersendsHTTP torequest to theserverin response we get response header which contains information of [Server, X-AspNet-Version,X-AspNetMvc-Version, X-Powered-By].

The server shows information of which web server is begin used.

X-AspNet-Versionshows information of which specific Asp.Net VersionUsed.

X-AspNetMvc-Versionshows information of which ASP.NET MVC version Used.

X-Powered-By shows information of which framework your website is running on.

Fig 39.Response header disclosing Version Information.

Solution:-

  1. For removingX-AspNetMvc-Version header

To remove response X-AspNetMvc-Versionwhich shows information of which ASP.NET MVC version used we have built in property in MVC.

Just set [MvcHandler.DisableMvcResponseHeader = true;] in Global.asaxApplication start event [Application_Start()] this will remove header it won’t be displayed any more.

Fig 40.Setting property in Global.asax to removeX-AspNetMvc-Version from header.

Fig 41.Response after removing X-AspNetMvc-Version from header.

2) For removingX-AspNet-Version and Server header

To remove response of Server header which shows information of which web server is begin used and along with that X-AspNet-Version headershows information of which specific Asp.Net Version Used.

Just add an event in [Application_PreSendRequestHeaders()] in global.asax and then to remove header we need to set theproperty as below.

protectedvoidApplication_PreSendRequestHeaders()
        {
Response.Headers.Remove("Server");           //Remove Server Header   
Response.Headers.Remove("X-AspNet-Version"); //Remove X-AspNet-Version Header
 }

Fig 42.Adding Application_PreSendRequestHeaders event in global.asax and then removing Response headers.

Fig 43.Response after removing X-AspNet-Version and Server from header.

3) For removingX-Powered-Byheader

To remove response of X-Powered-Byheaderwhich shows information of which framework your website is running on.

Just add this tag underSystem.webServerin Web.configfile will remove [X-Powered-By] header.

<httpprotocol>
<customheaders>

</customheaders>
</httpprotocol>

Fig 44.Adding custom Header tag in Web.configfor removing Response headers.

Fig 45.Response after removing X-Powered-By from header.

6) SQL Injection Attack.

SQL Injection attack is one of the most dangerousattacks it is ranked 1 in top 10 Vulnerabilitiesby OWASP2013 [Open Web Application Security Project] . SQL injection attack can give valuable data to theattacker that can lead to abig security breach and can also take full access to thedatabase server.

In SQL Injection attacker always try to enter malicious SQL statement which will get executed in thedatabase and return unwanted data to the attacker.

Fig 46.Sql injection attack example which shows how attack mostly occurs if you are using inline queries.

Simple View which shows User data

View Shows Single Employee data based on EmployeeID as displayed in below Snapshot.

Fig 47.Employee View which displays user data.

Simple View which shows All User data after SQL Injectionattack

In this Browser View as attacker saw Application URL which contains some valuable data which is ID [http://localhost:3837/EmployeeList/index?Id=2] attacker triesSQL Injectionattack as shown below.

Fig 48.Employee View which displays all User data after SQL injection.

After trying permutation & combination of SQL injection attack , theattackergets access to all User data.

Displaying SQL injection in Debug Mode

Here we can see in details how attacker passed maliciousSQL statement which gets executed in thedatabase.

Fig 49.Debug mode View of index Action Method.

SQL Profiler View of SQL statement

Fig 50.SQL Profiler View.

Solution:-

  1. Validate inputs
  2. Use of low-privileged database logins
  3. Use Parameterized queries
  4. Use ORM (e.g. Dapper , Entity framework )
  5. 5) Use Stored Procedures
  1. Validate inputs

Always validate input in both side Clientside and Server side such that no special characters are entered in inputs which allow anattacker to get into thesystem.

In MVC we use Data Annotations for Validation.

Data Annotations attribute aresimple rule that are applied on Model to validate Model data.

Client side validating inputs

Fig 51.Client side validating inputs.

Server side validating inputs

Model state is false this indicates that Model is not valid.

Fig 52.Server side validating inputs.

2) Give least-privileged database logins

Db_owner is default role for thedatabasewhich can grant and revoke access, create tables, stored procedures, views, run backups, schedule jobs can even drop the database.If this kind ofRole access is given to database then User who using can have full access and he can perform avarious activity on it. We must create anew user account with least-privileged and give only that privilege that user must access.

e.g. if theuser has to work related to Selecting , Inserting and Updating Employee details then only select, Insert and update permission should be provided.

Step to add new User and Provide Privilege

In this part, I have shown a small sample of how to create User provide specific permission to table.

  1. Creating New User
  2. View after creating User
  3. Selecting object that user can access (table)
  4. Choosing specific table to provide permission

Fig 53. Creating New Users and providing rights to Users.

After choosing table we are going providing permission to table as shown below, you can see we have only given permission to ‘Insert’,‘Select’, ‘Update’ for this User.

Fig 54.Giving permission for Insert, Select, Update.

With least-privileged,it will help us to safeguard database from attackers.

3) Use Stored Procedures

Stored procedures are a form of parameterized query .Using Stored Procedures is also one way to protect from SQL injection attack.

In below snapshot we have removed inline Query which we were using before now we have written code for getting data from database using stored procedure which helpsus to protect againstSQL injection attack ,then to stored procedure we need to pass parameter [@EmpID] and according to parameter it is going to get records from databaseafter passing parameter we have used CommadType [CommadType.StoredProcedure] which indicate we are using storedprocedure .

Note :- Always Use parameter with stored procedure if you do not use it still you are Vulnerable to SQL injection attack.

Fig 55.Using Stored Procedure for displaying Employees details.

After Using Stored Procedurelets Request GetEmployee View

Employee View which displays record.

Fig 56. Employees details View after using stored procedure.

Profiler View after using Stored Procedure

Displaying Trace of store procedure which we have used.

Fig 57.Trace of stored procedure Executed.

After Using Stored Procedure Let’s try SQL injection Attack Again

Fig 58.Trying SQL injection Attack after using stored procedure.

Displaying SQL injection attack execution in Debug Mode after using Stored Procedure

If you have look on parameter id [?Id=2 or 1=1] which contains MaliciousSQL script after passing it to stored procedure it shows anerror which indicates that it not get executed because parameter which we are passing is aninteger which only take numeric values as input if we pass MaliciousSQL script [?Id=2 or 1=1] it throws an error .

Fig 59.Stored procedure Used.

Fig 60.Trying SQL injection Attack after using stored procedure.

Profiler View after using Stored Procedure

Fig 61. Trace of stored procedure Executed.

Output:-

Fig 62.Displaying error after attacking by anattacker.

Meanwhile, you might think that if it was varchar datatype then we had successfully attack let's see ademoof it too.

Displaying SQL injection attack execution in Debug Mode after using Stored Procedure with different parameter @name

This is thesecond demo in which we have passed adifferent parameter to store procedure to see is it real protecting againstSQL injection attack.

Fig 63.Stored procedure Used.

Fig 64.Trying SQL injection Attack after using stored procedure.

Fig 65. Trace of stored procedure Executed.

Output:-

Fig 66. After using stored procedure if we try SQL injection attack then it does not get executed and no result is shown.

Use Parameterized queries

Using parameterized Queries is another solution to prevent againstSQL injection attack it is similar to stored procedure. Instead of Concatingstring, you need to add parameters to the SQLQuery and pass parameter value using the SqlCommand .

Fig 68.Parameterized Query also prevents against SQL injection attack.

Profiler View of parameterized Query

Fig 69. Trace of Parameterized query Executed.

Output:-

Fig 70. After using Parameterized query if we try SQL injection attack then it does not get executed and no result is shown.

Use ORM (Entity framework )

ORM stands for Object relational Mapper which maps SQL object to you domain object [C#].

If you are using entity framework properly you are not prone to SQL injection attack because entity framework internal uses parameterized query.

Normal execution of entity framework

Here we have passed thename as parameter [?name=Saineshwar].

Fig 71.Passing parameter after using Entity Framework.

Snapshot of the controller while Execution .

In debug mode we can see that we have passed name parameter from Querystring which we then passed it to Linq query to getting records.

Fig 72.Controller Execution.

Profiler View of Linq query

Entity Framework internally uses Parameterized query its true here is asnapshot.

Fig 73. Trace of thequery generated by Entity Framework.

Let’s try SQL injection Attackon Entity Framework

In this part we are tryingSQL injection attack on entity framework for that we have passed theparameter as [?name=Saineshwar or 1=1].

Fig 74. TryingSQL injection Attack after using Entity Framework.

Snapshot of thecontroller while Execution .

In debug mode we can see that we have passed name parameter from Querystring which we then passed it to Linq query to getting records but this time, it has malicious script along with normal parameter.

Fig 75. No output after try SQL injection Attack on Entity Framework.

Profiler View of Linq query

If you see trace closely it is considering thename and malicious script as asingle parameter which prevents it from SQL injection attack.

Fig 76. Trace of thequery generated by Entity Framework after tryingSQL injection attack.

7) Sensitive Data Exposure

All Website and Application always have database in which entire data is been stored .mean while we store Users personal information (which may contains Password , PAN number , Passport details ,Credit Card Numbers) in this we mostly encryptonly password right other data are stored in clear text which can lead to Sensitive Data Exposurewhenever an attacker attack he gets access to database if he finds the table where all this personal and financial details stored steal that information .

Fig 77.Sensitive Data Exposure.

A simple demo of howSensitive data is been sniffing.

Snapshot of Login page.

Simple code snippet of Login page which comes default if you are choosing Internet Template while creating aproject.

Fig 78.Login page Markup and Snapshot.

After having look at how Login page Mark and View looks now next we are going enter credentials and login.

Entering Credentials for Login

In Login page we are going to enter Username and Password to login into the application.

Fig 79.Entering Credentials.

Intercepting Login page by attacker to stealCredentials

When User enter Credentials in Login page and submit to server the data [username and password] is transferred to theserver in theclear text this data [username and password] can be intercepted by theattackerand steal your Credentials.

Below snapshot shows how your values can be intercepted by anattacker.

Fig 80.Intercepting Login page showing data in theClear form.

Solution :-

  1. Always Send Sensitive Data to Server in Encryptedformat using Strong Hashing with Seed (Random Hash).
  2. Always apply SSL to theWeb application.
  3. Do not store Sensitive data if want to store using Strong Hashing techniques

Always Send Sensitive Data to Server in Encrypted format using Strong Hashing with seed

In this demo,we are going useanMD5 algorithm with seed to encrypted data on client side and send to aserver such that it cannot be stolen by theattacker.

In below snapnot User enteringcredentials.

Fig 81.Entering Credentials after Encrypting data.

After entering User credentials when theuserclicks on loginbutton, this time, the user entered password get encrypted along with seed on theclient side using MD5 and then it is sent to theserver , in this process if anattackertries to sniff network then encrypted hash is only seen and which cannot be decrypted.

In details, you can see below snapshot where theattacker has sniff network.

Blue line in snapshot indicates Username.

The red line in snapshot indicates Encrypted Password along with theseed.

The green line in snapshot indicates seed value which is generated from theserver.

Fig 82.Intercepting login page after Encryption of data.

Till now we have seen snapshot how to do this let's see code snippet of it.

Login Model

Fig 83.LoginModel view.

Below is code snippet of [HttpGet] Login ActionMethod.

In this method, we are generating random hash [Seed] and then we are going to assign it to LoginModel and then pass it to Login View.

Fig 84.Generating and Assigning Random Hash to [hdrandomSeed] and then sending Model to View.

After assigning value [hdrandomSeed] to model in Login ActionMethod now we are going to use it on Login view as ahidden field.

Fig 85.Using the[hdrandomSeed] property as ahidden field on View.

Now after adding ahidden field on thepage now let's see how to Encrypt data using MD5 javascript along with theseed.

For doing this we are going to use jquery library 1.8 and md5.js librarywhen user enter Credentials and click on Log In button then we take password entered by User [ var password1 = $('#Password');] and generate Hash [ calcMD5(password).toUpperCase()]of it first then along with seed we again generate Hash [ var hash = calcMD5(seed + calcMD5(password).toUpperCase());] which is unique and then it is sent to server.

See below snapshot for details

Fig 86.Code Snippet of Client Side Encryption of MD5 along with Seed for generating Hash.

Debugging View of login page

In the variable session, you can see real time values which are generated when user click on login button.

Fig 87. Debug mode of Client-side Encryption.

After client side encryption now let's see attacker is able to intercept and see thepassword in clear text.

Intercepting Login page

In below snapshot, you can see password which is entered by theuser is in encrypted form and it cannot be understood by an attacker because it is combination hash of Seed + Password which is entered by User.

Fig 88.Interception of Login page.

After interception next we are going to see values how they are Posted to Login Action Method.

Login Action Method after posting Values from Login View

Here we can clearly see password is in encrypted form .

Fig 89.Login Action Method after posting Values from Login View.

In next step, we are going to compare password which is stored in adatabase for doing that first we are going to get thepassword from username which user has entered and then we are going to compare it against which is stored in thedatabase. The line which is marked green is Seed value along with that you can see Database stored password is marked as red which we get by passing Username and then yellow line which indicates that this password in posted from Login View and finally blue line which is combination of Database password and Seed wecompare it with password which is posted.

Fig 90.Code snippet of Login Action Method with pining real time values.

Finally,Sensitive data entered by User is Secure.

2) Use SSL for Securing Web application

SSL (Secure Sockets Layer) is Layer which Secure (Encrypted) communication between client and server such that any data [Banking details, Password, and anotherfinancialtransaction] passed from client and server is Secure (Encrypted) .

Fig 91.SSL (Secure Sockets Layer).

SSL is mainly Applied on theLogin page and payment gateways if you want to apply on theentire application then also you can apply.

If you want to know in details how to Enable SSL on IIS Server there is a good article from Scott Guthrie Sir blog check URL below.

http://weblogs.asp.net/scottgu/tip-trick-enabling-ssl-on-iis7-using-self-signed-certificates

3) Do not store Sensitive data in Database in a clear form

Always Try not to store Credit Card, Debit Card and financial details and other Sensitive details in thedatabasein Clear form . Always Use Strong Hashing techniques to encrypted data and then store in thedatabase. if anattacker gets direct access to thedatabase then all data in clear form can be Breached.

Below is alist of Algorithm which can be Used according to need.

Hash Algorithm

if someonewantsjust Hash then they can use Hash Algorithmwe mostly use Hash function for Encrypting Password.

SymmetricAlgorithm

If someonewants just one key for encryption and decryption then they can useSymmetricAlgorithm.

AsymmetricAlgorithm

If someonewants just one key for encryption (Public key) and another keydecryption (Private key) then they can useAsymmetricAlgorithm. E.g we can usethis when we are sharing Web Services and WebAPI with clients when theuser.

HashAlgorithm

  1. MD5
  2. SHA256
  3. SHA384
  4. SHA512

Example :-

Method to generate MD5 Hash

privatestring Generate_MD5_Hash(stringdata_To_Encrypted)
        {
using (MD5encryptor = MD5.Create())
            {
MD5md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(data_To_Encrypted);
byte[] hash = md5.ComputeHash(inputBytes);

StringBuildersb = newStringBuilder();

for (int i = 0; i <hash.length; i=""><p>Pass text to generate hash</p>
<pre lang="cs">string Hash = Generate_MD5_Hash("Hello");

Output

SymmetricAlgorithm

  1. Aes
  2. DES
  3. RC2
  4. Rijndael
  5. TripleDES

Example :-

Method of AES for Encryption

privatestringEncrypt_AES(stringclearText)
        {
stringEncryptionKey = "##SAI##1990##"; //Encryption Key
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
byte[] array = Encoding.ASCII.GetBytes("##100SAINESHWAR99##"); //salt

using (Aesencryptor = Aes.Create())
            {
Rfc2898DeriveBytespdb = newRfc2898DeriveBytes(EncryptionKey, array);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStreamms = newMemoryStream())
                {
using (CryptoStreamcs = newCryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
                    }
clearText = Convert.ToBase64String(ms.ToArray());
                }
            }
returnclearText;
        }

Method of AES for Decryption

privatestringDecrypt_AES(stringcipherText)
        {
stringEncryptionKey = "##SAI##1990##"; //Encryption Key
byte[] cipherBytes = Convert.FromBase64String(cipherText);
byte[] array = Encoding.ASCII.GetBytes("##100SAINESHWAR99##"); //salt

using (Aesencryptor = Aes.Create())
            {
Rfc2898DeriveBytespdb = newRfc2898DeriveBytes(EncryptionKey, array);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStreamms = newMemoryStream())
                {
using (CryptoStreamcs = newCryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
                    }
cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
returncipherText;
        }

Pass text to Encrypt Value

stringDataEncrypt = Encrypt_AES("Hello");   // Encrypting Data (Pass text to Encrypt)

Pass text to Decrypt Value

stringDataDecrypt = Decrypt_AES(DataEncrypt);  // Decrypt data (Pass Encrypt text to Decrypt)

Output

AsymmetricAlgorithm

  1. DSA
  2. ECDiffieHellman
  3. ECDsa
  4. RSA

Example :-

Method of RSA for Encryption

publicbyte[] Encrypt(stringpublicKeyXML, stringdataToDycript)
        {
RSACryptoServiceProviderrsa = newRSACryptoServiceProvider();
rsa.FromXmlString(publicKeyXML);
returnrsa.Encrypt(ASCIIEncoding.ASCII.GetBytes(dataToDycript), true);
        }

Method of RSA for Decryption

publicstring Decrypt(stringpublicPrivateKeyXML, byte[] encryptedData)
        {
RSACryptoServiceProviderrsa = newRSACryptoServiceProvider();
rsa.FromXmlString(publicPrivateKeyXML);
returnASCIIEncoding.ASCII.GetString(rsa.Decrypt(encryptedData, true));
        }

Output

8) Audit trail

Audit Trail in IT World is used to keep track of User activity on aWebapplication which he using , it is where important in detecting security problems, performance problems, and ApplicationsLevel Error problems. It also helps us to easily track where theproblemactually is and resolve it.

Fig 96.Audit.

Solution:-

  1. Keep Audit Trail of all User activity on Web Application and always Monitor it.

Keep Audit Trail of all User activity on Web Application and always Monitor it.

For Maintaining Audit Trail first we are going to create a table in thedatabase for storing Audit data with table name [AuditTB] After that we going create an ActionFilterAttribute with Name [UserAuditFilter]inside this on Action Executing we are going to write code for inserting data in thedatabase of theuser who are accessing our Application.

AuditTB Table View

In this table, we have taken common fields which we required to recognize User and his Activity.

Fig 97.AuditTB Table View.

After displaying table view now let’s have look on Model which is Creating according to Table.

AuditTB Model

publicpartialclassAuditTB
    {
publicintUsersAuditID { get; set; }
publicintUserID { get; set; }
publicstringSessionID { get; set; }
publicstringIPAddress { get; set; }
publicstringPageAccessed { get; set; }
publicNullable<system.datetime>LoggedInAt { get; set; }
publicNullable<system.datetime>LoggedOutAt { get; set; }
publicstringLoginStatus { get; set; }
publicstringControllerName { get; set; }
publicstringActionName { get; set; }
    }
</system.datetime></system.datetime>

After having look on Model which is generated now let’s createan ActionFilter with UserAuditFilter

UserAuditFilterActionfilter Code Snippet

UserAuditFilter is a Custom ActionFilter which we have created in this filter we insert data of User Activity into AuditTB table along with this we also check is User Logged in or not into application in thesame way we also insert IP address of User who is accessing theapplication , and time stamp of User logged in and out. For inserting this data we use ORM entity Framework.

publicclassUserAuditFilter : ActionFilterAttribute
    {
publicoverridevoidOnActionExecuting(ActionExecutingContextfilterContext)
        {
AllSampleCodeEntitiesappcontext = newAllSampleCodeEntities();
AuditTBobjaudit = newAuditTB();
//Getting Action Name
stringactionName = filterContext.ActionDescriptor.ActionName;
//Getting Controller Name
stringcontrollerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var request = filterContext.HttpContext.Request;
if (HttpContext.Current.Session["UserID"] == null) // For Checking User is Logged in or Not 
            {
objaudit.UserID = 0;
            }
else
            {
objaudit.UserID = Convert.ToInt32(HttpContext.Current.Session["UserID"]);
            }
objaudit.UsersAuditID = 0;
objaudit.SessionID = HttpContext.Current.Session.SessionID; // Application SessionID
// User IPAddress
objaudit.IPAddress =
request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;
objaudit.PageAccessed = request.RawUrl;  // URL User Requested
objaudit.LoggedInAt = DateTime.Now;      // Time User Logged In || And time User Request Method
if (actionName == "LogOff")
            {
objaudit.LoggedOutAt = DateTime.Now; // Time User Logged OUT
            }        
objaudit.LoginStatus = "A";
objaudit.ControllerName = controllerName; // ControllerName
objaudit.ActionName = actionName;         // ActionName
appcontext.AuditTBs.Add(objaudit);
appcontext.SaveChanges();                    // Saving in database using Entity Framework
base.OnActionExecuting(filterContext);
        }
    }

Registering UserAuditFilter in global action filter

Global action filters are mainly used for error handling and logging.

If you have a condition in which you want to apply Action Filter on all action Method in theproject then you can use global action filters. Here we need global action filters because we want to track every request of theuser for Audit trail hence we have used.

Fig 98.Adding UserAuditFilter to Global filter Collection.

Output

The data which got inserted while User Request pages and do some activity in Audit Table.

Fig 99.Audit table View after Insertion of data.

9) Broken authentication and session management

If Authentication and Sessionmanagement are not properly Implemented in a webapplication which mayallow anattacker to steal apassword , session tokens , cookies and such issue may also allow anattacker to get access to theentire application and breach all user credentials.

Ways attacker can steal data

  1. Not Secure connection (Not Using SSL)
  2. Predictable login credentials
  3. Not storing credentials Encrypted form.
  4. Improper Application logout.

Attacks Possible

  1. Session Fixation

Before finding asolution how to prevent this attack lets have a look on small demo how Session Fixation attack occurs.

Whenever ausersends first request to server the login page is loaded then User enter valid Login creditsto login in web application after successful login we assign some values in session to recognize Unique User,meanwhile a [“ASP.NET_SessionId”] cookie is Added to thebrowser for recognizingspecific User who has sent arequest and [“ASP.NET_SessionId”] cookie value will be always sent to theserver on every requesttill you are not logout from theapplication and on logout, we basically write code for removing session values which are created but we do not remove [“ASP.NET_SessionId”] cookie which is created on Login . this value helps anattacker to perform Session Fixation attack.

Fig 100.Session Fixation.

Demo of Session Fixation

When we access login page we do not have any [“ASP.NET_SessionId”] cookie in thebrowser as we can see in cookie manager.

After User Enter Valid Credentials

After entering Valid Login Credentials [“ASP.NET_SessionId”] Cookie is added to thebrowser.

Note :- When any data is saved into the Session[“ASP.NET_SessionId”] cookie is created and added to theuser browser.

After Logging out from Application Cookie still exists in browser

After Logout out from application Still [“ASP.NET_SessionId”] Cookie Exits.

Note: Pre cookie and post cookie are same which can lead to the session fixation.

Let’s do Some Session Fixation

The [“ASP.NET_SessionId”] Cookie which is not removed after logout which helps attacker for doing session fixationI will open abrowser (chrome) in that I will enter URL [http://localhost:3837/] of application in which we are going to do session fixation.

After Entering URL in thebrowsernow lets check we have any [“ASP.NET_SessionId”] Cookie Created here oh we don’t have any Cookie.

Cookie which is already Created in Firefox browser

In this view, I have shown [“ASP.NET_SessionId”] cookie which is created in firefox browser when theuser logged in.

Note :- For managing Cookie, I have installed Cookie Manager+ addon in Chrome browser.

After having aview on [“ASP.NET_SessionId”] cookie in firefox now lets Create [“ASP.NET_SessionId”] cookie in Chrome browser similar to Cookie which is in Firefox browser with same [“ASP.NET_SessionId”] Cookie Name and Values.

Created New [“ASP.NET_SessionId”] Cookie in Chrome browser similar to Cookie created in Firefox browser.

This is astep where we have Fixed Session this session is live on another browser[firefox] we have copied values similar to that and created a [“ASP.NET_SessionId”] Cookie and assign similar values of SessionID to this Cookie.

Note :- For Adding Cookie I have installed Edit this Cookie addon in Chrome browser

After fixing cookie now we no more require any login to theapplication if we just enter Inner URL of application we get direct access because this session is created after authentication.

Solution :-

  1. Remove[“ASP.NET_SessionId”]after logout.
  2. Securing Cookies
  3. Use SSL for Securing Cookies and Session

Remove [“ASP.NET_SessionId”] after logout

On logout we are removing Session values long with that we are removing [“ASP.NET_SessionId”] Cookie from browser.

//
// POST: /Account/LogOff
publicActionResultLogOff()
{
//Removing Session
Session.Abandon();
Session.Clear();
Session.RemoveAll();

//Removing ASP.NET_SessionId Cookie
if (Request.Cookies["ASP.NET_SessionId"] != null)
    {
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-10);
    }

if (Request.Cookies["AuthenticationToken"] != null)
    {
Response.Cookies["AuthenticationToken"].Value = string.Empty;
Response.Cookies["AuthenticationToken"].Expires = DateTime.Now.AddMonths(-10);
    }

returnRedirectToAction("Login", "Account");
}

Securing cookie

For securing cookies On Login [HttpPost] Action Method we are goingto Create a New Session in that Session [Session["AuthenticationToken"]] we are going save NewGuid along with that we are going to add a cookie with Name ["AuthenticationToken"] and it will also have same Value [Guid] which we have stored in Session.

Code Snippet

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
publicActionResult Login(LoginModel model, stringreturnUrl)
{
if (ModelState.IsValid)
    {   //Getting Pasword from Database
varstoredpassword = ReturnPassword(model.UserName);
// Comparing Password With Seed
if (ReturnHash(storedpassword, model.hdrandomSeed) == model.Password)
        {
Session["Username"] = model.UserName;
Session["UserID"] = 1;

// Getting New Guid
stringguid = Convert.ToString(Guid.NewGuid());
//Storing new Guid in Session
Session["AuthenticationToken"] = guid;
//Adding Cookie in Browser
Response.Cookies.Add(newHttpCookie("AuthenticationToken", guid));

returnRedirectToAction("Index", "Dashboard");
        }
else
        {
ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }
return View(model);
}

Code snippet description

Creating a new Guid.

// Getting New Guid
stringguid = Convert.ToString(Guid.NewGuid());

Saving a new Guid in Session.

//Storing new Guid in Session
Session["AuthenticationToken"] = guid;

Saving a new Guid in Cookie and adding.

//Adding Cookie in Browser
Response.Cookies.Add(newHttpCookie("AuthenticationToken", guid));

After storing data in session and adding a cookie in thebrowser now let’s match this values on every request and check these values are similarif not then we are going to redirect to Login page.

For doing this part I am going to add an AuthorizationFilter in theproject and inside that we are going to write logic for checking Session and cookie values are similar or not.

AuthenticateUser ActionFilter

If you check below code snippet I have created an AuthorizationFilterwith name AuthenticateUser this filter we are inheriting IAuthorizationFilter Interface and FilterAttribute class with this we are implementing method inside interface [OnAuthorization] and write whole logic in this method.

using System;
usingSystem.Web.Mvc;

namespaceMvcSecurity.Filters
{
publicclassAuthenticateUser : FilterAttribute, IAuthorizationFilter
    {
publicvoidOnAuthorization(AuthorizationContextfilterContext)
        {
stringTempSession =
Convert.ToString(filterContext.HttpContext.Session["AuthenticationToken"]);
stringTempAuthCookie =
Convert.ToString(filterContext.HttpContext.Request.Cookies["AuthenticationToken"].Value);

if (TempSession != null&&TempAuthCookie != null)
            {
if (!TempSession.Equals(TempAuthCookie))
                {
ViewResult result = newViewResult();
result.ViewName = "Login";
filterContext.Result = result;
                } 
            }
else
            {
ViewResult result = newViewResult();
result.ViewName = "Login";
filterContext.Result = result;
            }
        }
    }
}

Code snippet description

In this method first we are going get session and cookie values.

stringTempSession =                 Convert.ToString(filterContext.HttpContext.Session["AuthenticationToken"]);
stringTempAuthCookie =  Convert.ToString(filterContext.HttpContext.Request.Cookies["AuthenticationToken"].Value);

After getting values from session and cookie now we are going check that both session and cookie values are not null after that we are going see values are equal of both session and acookie if they are not then we are going to redirect to login page.

if (TempSession != null&&TempAuthCookie != null)
{
if (!TempSession.Equals(TempAuthCookie))
    {
ViewResult result = newViewResult();
result.ViewName = "Login";
filterContext.Result = result;
    } 
}
else
{
ViewResult result = newViewResult();
result.ViewName = "Login";
filterContext.Result = result;
}

After understanding codesnippet now we are going apply this filter on every controller which user access when he is logged in to application.

Applying AuthenticateUser Filter

Apply this filter on every controller which user access when he is logged into theapplication.

After applying Action filter on all the controller which user access after Logged into theapplication.

Now if theattackerknows[“ASP.NET_SessionId”] cookie valueand a new cookie[Cookies["AuthenticationToken"]] value he will still not able to Session Fixation attack here because the new [Cookies["AuthenticationToken"]] contains GUID which is unique and same values is stored in Session [Session["AuthenticationToken"]] on Web Serverbut attacker can’t know the Session value that is stored on the web server and this values keep changing every time when user is logging to application and the old session values which attacker used to do attack will not work in this scenarios.

Finally, if we will allow those User access to theapplication who has valid Session["AuthenticationToken"]value and Cookies["AuthenticationToken"]value.

Realtime Values of both Cookies.

Use SSL for Securing Cookies and Session Values

SSL (Secure Sockets Layer) is Layer which Secure (Encrypted) communication between client and server such that any data [Banking details, Password, Session ,Cookie and anotherfinancial transaction] passed from client and server is Secure (Encrypted).

Fig 111.SSL (Secure Sockets Layer).

10) Unvalidated Redirects and Forwards

In all web application, we do redirect from one page to another page and sometimes we redirect to another application too but while redirect we won't validate URL which we are going redirect which causesUnvalidated Redirects and Forwards Attack.

This attack mostly uses to phish User to get Valuable details (User Credentials) or to install maliciousmalware to the User computer.

Examples

In below snapshot, you will see Simple MVC application URL along with that a created malicious URL by anattackerthat redirects users to a malicious site that performs phishing and installs malware into user computers.

Fig 112.Crafted URL by anattacker.

Original URL :-http://localhost:7426/Account/Login

Crafter URL by Attacker :-?returnUrl=https://www.google.co.in

Attack Scenario

In this attack User gets Email from attacker which contains offer related to Ecommerce shopping when user click on link given below he is redirected to shopping site [http://demotop.com] but if you see URL closely you will see that this URL contains redirect [http://demotop.com/Login/Login?url=http://mailicious.com] now after entering valid Username and Password the User will be redirected to Malicious site [http://mailicious.com] which is similar to [http://demotop.com] shopping site . On theMalicious site it will show Message “Invalid Username and Password” then again User will enter Username and Password and he will be redirected back to Original shopping site but meanwhile User Credentials are stolen in this attack.

Fig 113.Unvalidated Redirects and ForwardsAttack Scenario.

Solution

  1. Simply avoid using redirects and forwards.
  2. If you still want to use redirects and forwards then validate URL first.
  3. Use Url.IsLocalUrlto Preventing redirects and forwards in MVC.

Using Url.IsLocalUrlin MVC

Below is asnapshot of thelogin page in MVC which contains redirect URL to www.google.com when user enter Username and password then he will be redirected to www.google.comwhich is invalid to prevent this in MVC4 we have built in method called as Url.IsLocalUrlwhich checks that redirect URL which is Crafted is Local or not if not then it will not redirect it.

Fig 114.Login page in MVC with Redirect URL.

After understanding how redirect is passed not let’s check how this URL gets checked and executed.

The below [HttpPost] Login method get called when user enter Credentials and submit theform along with that redirect URL is also get posted which may containmalicious URL. For showing demo I have just checked that Username and password is not null after that we are calling RedirectToLocalAction Method and to this method we are going to pass redirect URL (returnUrl).

Fig 115.Login Post Action Method with returnURL.

After passing URL (returnUrl) to RedirectToLocalAction Method method then it is going pass URL to IsLocalUrl Method [Url.IsLocalUrl(returnUrl)] which is going check URL is local or not and return aboolean value if it is not then it will redirect to Home page else will redirect to returnUrl which is passed.

[True if the URL is local]
[False if URL is not local]

Fig 116.RedirectToLocal Action Method which checksreturnUrl is Local or Not.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

saineshwar bageri
Software Developer Mahaonline LTD
India India
Indian Software Developer and MVP from c-sharpcorner working on .Net Web Technology
( Asp.net , C# , Sqlserver , MVC , Windows ,Console Application, javascript , jquery , json , ORM Dapper) and also freelance developer.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
GeneralMy vote of 5 Pin
Mohan_Patil7-Aug-17 4:12
professionalMohan_Patil7-Aug-17 4:12 
GeneralMy vote of 5 Pin
Karthik Bangalore25-Jul-17 19:07
mvpKarthik Bangalore25-Jul-17 19:07 
GeneralRe: My vote of 5 Pin
saineshwar bageri25-Jul-17 19:34
membersaineshwar bageri25-Jul-17 19:34 
PraiseGreat Pin
Ethan19881-Jun-17 7:30
memberEthan19881-Jun-17 7:30 
GeneralRe: Great Pin
saineshwar bageri25-Jul-17 19:34
membersaineshwar bageri25-Jul-17 19:34 
GeneralMy vote of 5 Pin
Mukul00331-May-17 1:44
professionalMukul00331-May-17 1:44 
Question10 Points to Secure Your ASP.NET MVC Applications. Pin
Member 130099371-Apr-17 3:08
memberMember 130099371-Apr-17 3:08 
QuestionGood Pin
keyur soni11-Dec-16 21:59
memberkeyur soni11-Dec-16 21:59 
QuestionRemove response header suggested approach doesn't work for .Net 4.5 Pin
pankaj28720-Nov-16 11:23
memberpankaj28720-Nov-16 11:23 
GeneralMy vote of 5 Pin
Shohel Ahsan26-Sep-16 22:59
memberShohel Ahsan26-Sep-16 22:59 
GeneralMy vote of 5 Pin
Anurag Gandhi11-Sep-16 23:07
professionalAnurag Gandhi11-Sep-16 23:07 
GeneralMy vote of 5 Pin
Renju Vinod11-Sep-16 20:46
professionalRenju Vinod11-Sep-16 20:46 
QuestionMy vote of 5 Pin
Ahmet Abdi9-Sep-16 18:24
memberAhmet Abdi9-Sep-16 18:24 
GeneralVery nice articles Pin
Anjani7869-Sep-16 10:05
memberAnjani7869-Sep-16 10:05 
QuestionExcellent Pin
Debendra02569-Sep-16 8:04
memberDebendra02569-Sep-16 8:04 
Generaldetailed w.solutions Pin
SSBO17-Aug-16 23:58
memberSSBO17-Aug-16 23:58 
GeneralRe: detailed w.solutions Pin
saineshwar19-Aug-16 17:05
membersaineshwar19-Aug-16 17:05 
PraiseThanks Pin
Member 1268085715-Aug-16 20:21
memberMember 1268085715-Aug-16 20:21 
QuestionAmazing Pin
Thiago Vaini9-Aug-16 4:05
professionalThiago Vaini9-Aug-16 4:05 
QuestionInteresting Pin
tbayart9-Aug-16 1:31
membertbayart9-Aug-16 1:31 
PraiseExcellent Article- has lot of insight Pin
Vijay Bhasker Reddy CH8-Aug-16 21:13
memberVijay Bhasker Reddy CH8-Aug-16 21:13 
QuestionGood Post Pin
CJ_P5-Aug-16 10:41
memberCJ_P5-Aug-16 10:41 
AnswerRe: Good Post Pin
saineshwar5-Aug-16 17:22
membersaineshwar5-Aug-16 17:22 
GeneralMy vote of 5 Pin
CJ_P5-Aug-16 10:23
memberCJ_P5-Aug-16 10:23 
QuestionVery nice article Pin
thangchung4-Aug-16 20:53
professionalthangchung4-Aug-16 20:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171019.1 | Last Updated 5 Aug 2016
Article Copyright 2016 by saineshwar bageri
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid