10 Points to Secure ASP.NET Core MVC Applications

Jignesh Trivedi  Print 
14 Sep 2018
 
Advanced
813

As we aware that framework .net core 2.1 is now under LTS (Long Term Support) releases. So, this framework is more stable and may use to create the large application. When we talk about the web application, security is a major concern. In this article, I have explained about 10 points that need to consider before start application development. In this article, I will cover the following points

  1. Cross-Site Scripting (XSS)

  2. Cross-Site Request Forgery (CSRF)

  3. SQL Injection

  4. Do the Proper Error Handling

  5. Enforce SSL and use HSTS

  6. XXE (XML External Entities) attack

  7. Improper Authentication & session management

  8. improper Authorization

  9. Do not use components with Known Vulnerabilities

  10. Version Discloser

Cross-Site Scripting (XSS)

It is kind of computer security vulnerability found in web application that allows attackers to inject client-side scripts or malicious code into web pages which is viewed by the other users. It is different from other web attack like SQL injection that does not directly target web app. In XSS, mostly attack happened via the input field, query string, request headers.

Types of Cross-Site Scripting (XSS) vulnerabilities

There are mainly three types of XSS vulnerabilities: Reflected XSS, DOM-based XSS and Stored XSS. Reflected XSS is most common type of XSS vulnerability. Here, attacker may inject the payloads (also refer as metadata) to the victim so that the payload script is part of request sent to the web server and reflected with http response. Document Object Model (DOM) based XSS is an advanced type of XSS attack and it is possible when client script generates DOM by using provided data. In stored XSS, attacker inject the script which stored into the target application permanently. For example, some malicious script can be injected to site in any input field such as comment field and the victim views this page in a browser, the script will run in to the browser.

How to prevent XSS

Following are some solutions to prevent XSS.

Sanitizing user input :This is helpful to prevent XSS attack on site that allows HTML markup as input. It means that encode the HTML that is stored. The Razor engine automatically encode all the inputs so that the script part which add as an any field is never executed. The using @ directive, we can apply encoding rule to the variable.

Encoding the URL : Many applications use Query String to transfer the data from one page to another page. The XSS attack can be possible on query string data due to it is not encoded. Using UrlEncode and UrlDecode method of Microsoft.AspNetCore.WebUtilities class, we can encode and decode the URL with ASp.net code 2.0 and above version.

Input Validation : Some time HTML character does make sense for user input. we can put the validation (client and server side both) that prevent the malicious data that harming a website.

Cross-Site Request Forgery (CSRF)

It also known as Session riding and pronounced as XSRF. In this method of attack, attacker copies forge as a trusted source and send the data to the site. The site processes this information believe that this is coming from trusted source. This kind of attack can be destroying both client relation and business. The example of CSRF is unauthorized fund transfers, data theft etc.

Mostly this is done through creating forged site and it internally hits the genuine site and by using already established user session, attacker is done some malicious activity. For example, user is transferring fund from one account to another account and trusted connection established between user and bank site. At the same time user click on malicious like from junked email (that sent by the attacker). Because of the secure session is established between user and bank site, attacker use this connection and do some malicious activity such as fund transfer. However, it is vulnerability at server (web application) side not an end user side.

Solution

Using tag helper "asp-anti forgery", we can enable/disable anti-forgery for the page. If this tag helper value is set to "true", it means that it enables the anti-forgery for this page. And using ValidateAntiForgeryToken attribute, we can check whether the token is valid or not at server side (controller / action method). It also can be ignored by using “IgnoreAntiforgeryToken” attribute

Example
 <form asp-controller="Account" asp-action="Login" asp-antiforgery="true" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
 ….
 ….
 </form>
 
 [ValidateAntiForgeryToken]
 public class AccountController : Controller
 {
 public IActionResult Login()
 {
 return View();
 }
 [IgnoreAntiforgeryToken]
 public IActionResult Method1()
 {
 return View();
 }
 }
 

SQL Injection

SQL Injection is a most common attack that inject malicious SQL code for database and unauthorized user can get the information. For example, user get the information that he/she did not have right to visualize using SQL injection. In this attack, hacker is always trying to inject SQL statement that will get executed on the database and get unassessed data.In this following example code snap, the attacker/hacker can easily do the SQL injection. Here, I have modify the input (id that is visible as query string), so system will return all the records of user instead of specific user.

How to prevent SQL Injection

Following are some solutions to prevent SQL Injection.

  1. Use Parameterized Query or stored procedureUsing the parameterized query or stored procedure, we can prevent SQL injection. It is better to use stored procedure instead of inline query. If you want to use inline query, we must use parameterized query to prevent our application from SQL Injection.

     SqlCommand cmd1 = new SqlCommand("select * from User where id = @id", connection);
     SqlParameter param = new SqlParameter();
     param.ParameterName = "@id";
     param.Value = id;
     cmd.Parameters.Add(param);
     …
     …
    
  2. se any O/RM (Object-relational mapping) such as Entity Framework O/RM maps SQL object such as table, view to our domain object such as class. Most of the ORM is generate parameterized query internally to fetch the record from database.

Do the Proper Error Handling

Some time, we are not doing proper error handling. So, some of the sensitive information are exposed in term of error such as database object name (table, stored procedure etc.), file location etc. This kind of information can be used by attacker / hacker to do attack on the web site.

How to prevent

It can be preventing by using creating custom error page that will display when any error occurred, or we can write the code to do custom error handling.In the first solution, we need to create page that have generic message and it need to be configured Configure method of startup class.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
 {
 ….
 ….
 ….
 app.UseExceptionHandler("/Home/Error");
 ….
 ….
 }
 

Alternatively, we can write some custom code to do exception handling such as try-catch block, exception handler or exception filter.

Enforce SSL and use HSTS

SSL enable us to establish encrypted connection between web server and browser. It ensures that all the data that transmitted between web server (application) and browser are encrypted and not change during transition. To secure our application, we can use HTTPS (Hyper Text Transfer Protocol Secure) protocol. There are many advantages using HTTPS such trust, verified data, Integrity of Data etc.

ASP.net core 2.1 and later version enable us to create application that configured over HTTPS. We can also configure HTTPS with ASP.net Core before the .NET core framework 1.1 but it was some difficult to configure.There is option available to configure our web application over HTTPS when we are creating a web application with Visual Studio. In the template of web application, HTTPS is enabling for the application.

HSTS (HTTP Strict Transport Security Protocol)

It is a web security policy that protect our web application from downgrade protocol attacks and cookie hijacking. It forces web server to communicate over HTTPS connection. It always rejects insecure connections. The Asp.net core templet by default add HSTS middleware. It is not recommended to use in development environment as browser is cache the HSTS header.

 public void Configure(IApplicationBuilder app)
 {
 ….
 ….
 if (env.IsDevelopment())
 {
 ….
 }
 else
 {
 …
 app.UseHsts();
 }
 ….
 ….
 }
 

There are couple of options available that can be overrides to configure HSTS. Following are the options

  • MaxAge : It is time span that define the max age of Strict-Transport-Security header valid. Default value is 30 days.

  • IncludeSubDomains : It boolean type and if it set to true, Strict-Transport-Security header available for sub domain as well.

  • Preload : Using this property, we can add preload for Strict-Transport-Security header.

  • ExcludedHosts : it is list of host name will not add the HSTS header

 
 public void ConfigureServices(IServiceCollection services)
 {
 ….
 ….
 services.AddMvc();
 services.AddHsts(options =>
 {
 options.IncludeSubDomains = true;
 options.Preload = true;
 options.MaxAge = TimeSpan.FromHours(1500);
 options.ExcludedHosts.Add("myDummySite.com");
 });
 
 }
 

The default template also adds another middleware that redirects request from non-secure secure HTTP. It uses default redirect status code (307) to redirect the request. We can also configure this middleware based on our requirement. We can override the default option by adding AddHttpsRedirection method to ConfigureService method of startup class. Here we can configure default redirect status code and https port

 public void ConfigureServices(IServiceCollection services)
 {
 ….
 services.AddHttpsRedirection(options =>
 {
 options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
 options.HttpsPort = 9001;
 });
 ….
 }
 public void Configure(IApplicationBuilder app)
 {
 ….
 ….
 app.UseHttpsRedirection();
 ….
 ….
 }
 

XXE (XML External Entities) attack

XXE (XML External Entity) attack is possible on the application that parses XML input. The possible reason of this attack is XML input contains reference of external entity which weakly configured in XML parser. It may happen due to disclosure of confidential data, SSRF (server-side request forgery), port scanning by the hacker where application (XML parser) hosted, denial of service (Dos), etc. Hacker / Attacker can use XML to cause a Denial of Service attack by injecting entities within entities. This type of attack refers as “Billion Laughs Attack”. As the result, system required more resource to complete the task and due to high utilization server may crash.

Solution

If you are using "XmlTextReader" class to parse the XML, it has property "DtdProcessing" that must be set to Prohibit or Ignore. If we have set DtdProcessing property of XmlTextReader to "Prohibit", system will throw the exception as DTD (Document Type Definition) is identified and if we have set DtdProcessing property of XmlTextReader to "Ignore", system will ignore DTD specifications and continue to process the document.

 
 XmlTextReader reader = new XmlTextReader("fileName with path");
 reader.DtdProcessing = DtdProcessing.Prohibit;
 
 while (reader.Read())
 {
 …
 …
 }
 

Improper Authentication & session management

Sometimes, we do not maintain proper authentication that allows the hacker to steal user credentials in terms of session and cookies. Using these type of user access, hacker can take complete access of the application. Following are some ways to stolen the user credentials.

  • Non-secure connection (without SSL)

  • Login credential easy hack-able or weak credential

  • Problem with session such as session id exposed in URL, session have a long timeout, etc.

  • Improper logout from application (do not killing user session on logout)

After successful login in the web application, some cookies are set to the browser to identify the user that are logged-in. This cookies are always sent to web server with every request. On logout, we generally remove the session but forget to remove cookies. These cookies may be used by hacker to do attack on web server. Default cookie name for the .net core web application is “.AspNetCore.Session” and this default cookie does not specify the domain. Using session option, we can override cookie setting.

 public void ConfigureServices(IServiceCollection services)
 {
 ….
 services.AddSession(options =>
 {
 options.Cookie.Name = ".MyApplication.Session";
 })
 ….
 }
 

Solution is very simple: remove the cookies are successful logout, use secure HTTP to secure cookies and session.

 //Remove session
 HttpContext.Session.Clear();
 
 // Removing Cookies
 CookieOptions option = new CookieOptions();
 if (Request.Cookies[".AspNetCore.Session"] != null)
 {
 option.Expires = DateTime.Now.AddDays(-1);
 Response.Cookies.Append("Myapplication.Session", "", option);
 }
 

If you are working with built-in identity membership, so “SignOutAsync” method of SignInManager class will take care about removing all your cookies after logout.

 public async Task<IActionResult> Logout()
 {
 await signInManager.SignOutAsync();
 …
 …
 }

As describe in preceding section, SSL enable us to do make secure communication connection between server and client so that any data that transited between server and client are encrypted. There are some cookie options need to set to secure cookies and session

  • HttpOnly : It indicates whether client-side code able to access the application cookies or not. If it is set to HttpOnlyPolicy.Always, client-side script is not able to access the application cookies.

  • Secure : It indicates whether cookies are transmitted using SSL (over HTTPS) only. If it is set to true (internally), the cookies are only transmitted over SSL connection. It can set to true by using CookieSecurePolicy.Always and CookieSecurePolicy.SameAsRequest option.

  • SameSite : It is same site mode for cookies.

 public void Configure(IApplicationBuilder app)
 {
 …
 …
 
 app.UseCookiePolicy(new CookiePolicyOptions
 {
 HttpOnly = HttpOnlyPolicy.Always,
 MinimumSameSitePolicy = SameSiteMode.Strict,
 Secure = CookieSecurePolicy.SameAsRequest
 });
 …
 }

improper Authorization

Authentication is process of checking the identity of the user that accessing our application. Most of the application has login feature and application validate user identity against any trusted source such as database or external login providers (i.e. Facebook, Gmail, twitter etc.). This process is called Authentication. Authorization is process of validating privileges to access a resource of the application. After successful login to the application, authorization mechanism checks whether login user has privileges to access the application resource.

Using “Authorize” attribute we can turn on the authorization for any controller or individual action method. Some time, due to the laziness of developers, they miss to put authorize check of controller or action and, they bypass the authorization in same case. It causes the security hole in the web application. Some time, developers also miss to put proper authorization for the controller or action method. For example, some of the page can be accessible by the unauthorized role user due to improper role-based authorization.

Solution

Solution is very straight forward, make sure authorization works as expected before web application moves to production environment. ASP.net core have very rich model for authorization such as Policy-based authorization, claim-based authorization, etc., we can use these models in the complex scenario to authorization.

Do not use components with Known Vulnerabilities

Nowadays, we are using many third-party JavaScript libraries in our development of web application. It is just impossible to develop application without such libraries. These libraries may have security flaws which make a web application vulnerable.The most common security vulnerabilities with-in JavaScript includes CSRF, XSS, buffer overflows, etc. As describe preceding section of this article, XSS allows hacker to put malicious code into the trusted page and this code will execute in user's browser. CSRF allows the hacker to utilize a user’s browser session as trusted source and send the other sites. Buffer overflow occurred when hacker sent very large data to the site that hold by web site resulting web site may be crash.

For the JavaScript library, there is full prove documentation that list down all the vulnerabilities. There is some public site, they log the vulnerabilities for the popular JavaScript framework or plugin. For example, jQuery’s vulnerabilities are list down on CVE website.

Solution

  • Do not download any plugin or library from untrusted source. Use trusted source such as npm. It may reduce the chance of including a malicious or modified component

  • Do not use any untrusted library in application

  • Always use updated version of library (it may fix some critical security defect in latest version)

  • Always remove unused plugin, files, component from the application

  • Monitor the library's Vulnerabilities from the source such as NVD and CVE

  • Here, I have talk about JavaScript library, but there are many security vulnerability incidents are log for server-side framework.

Version Discloser

The request and response object contain may information such as request method, remote address, server X-Powered-By, etc. Some of them are very sensitive such as X-Powered-By, Server etc. They must not disclose to the end user because attacker may use this information to do attack. It may possible that some framework version may encounter security Vulnerabilities and using these Vulnerabilities, attacker may brake our system.

As seen in above snap, we can get information such as server, X-Powered-By and X-sourcefiles. The Server property indicate which server is used to host application, the X-Powered-By indicate the information about the framework and X-SourceFiles is only available in debugging modules in IIS / IIS express.

Solution

Removing headers that contains the sensitive information. We can remove server header by setting up AddServerHeader to false where we configure the server. In following an example, I have remove server header from Kestrel server.

 
 public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
 WebHost.CreateDefaultBuilder(args)
 .UseKestrel(c => c.AddServerHeader = false)
 .UseStartup<Startup>();
 

We can remove X-Powered-By header either by using web.config or from IIS setiing.

 
 <?xml version="1.0" encoding="utf-8" ?>
 <configuration>
 <system.webServer>
 <httpProtocol>
 <customHeaders>
 <remove name="X-Powered-By" />
 </customHeaders>
 </httpProtocol>
 </system.webServer>
 </configuration>
Summary

In this article, I have try to cover top 10 possible attacks on our Asp.net core application and how to prevent our application from such attack.

Hands-on Learning
+