Protecting ASP.Net Core App from common attacks

The goal of this article is to give you an understanding of different areas that a ASP.Net Core developer should concentrate while designing a web application to make more secure. This article discusses a wide range of vulnerability that can be exploited by the hacker and the countermeasure to dodge the same.

Lets find out what are the basic security measurements we can apply to ASP.Net core application.

Applying SSL

A web application is typically deployed to the internet, and the browser talks to the application over the internet. Everything that goes over the wire is susceptible to eavesdropping. Any person that can position himself between the browser and the website can listen in. That person is also known as the man in the middle. Besides eavesdropping, the man in the middle also can execute attacks when the site is unprotected. This is the reason you have to encrypt the connection by using SSL. The HTTP protocol supports this by using the HTTPS scheme. In that way, the man in the middle can’t see what’s going on.

For an example, we can demonstrate how TLS security can be applied for a web application developed using the MVC framework. There are lots of examples about how to implement the authentication or authorization using build-in tools or using 3rd party tools. Also, there are no extra security measures taken on top of what ASP.NET Core MVC already offers. The application is built using the standard MVC pattern using repositories that are injected into the controllers. For an application like this we can enforce SSL on the controller by using the RequiredHttps attribute above it as below.

[Route("[controller]")]
[RequireHttps]
public class LoggingController : Controller
{
private readonly IBusClient _busClient;

public LoggingController(IBusClient busClient)
{
_busClient = busClient;
}

[HttpPost("")]
public async Task<IActionResult> Post([FromBody]CreateLog command)
{
command.Id = Guid.NewGuid().ToString();
await _busClient.PublishAsync(command);

return Accepted($"logging /{command.Id}");
}
}

​If you try to access this controller from http channel it would prevent it. but there is a problem in this method. It always requires https channel to access the controller. When running from Visual Studio, it uses IIS Express as a web server. IIS Express uses no standard port for HTTP as well as HTTPS when you enable it. All will RequireHttpsAttribute does when it detects an HTTP call is a permanent redirect to the same URL, but now with the HTTPS protocol. This won’t work using non-standard ports. Hence , this would hurt us when we develop our app and try to debug the app using developer consoles and tools. Apart from this, we need to add the attribute to all our controllers separately.

The easiest solution to this is injecting RequireHttps Attribute as a filter in the startup class of the application as follows.

public class Startup
{
private readonly IHostingEnvironment _env;

public Startup(IConfiguration configuration,IHostingEnvironment env)
{
Configuration = configuration;
_env = env;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{


services.AddMvc();

if (!_env.IsDevelopment())
{
services.Configure<MvcOptions>(options => options.Filters.Add(new RequireHttpsAttribute()));
}

services.AddRabbitMq(Configuration);
services.AddMongoDB(Configuration);
services.AddScoped<IEventHandler<LogCreated>, LogCreatedHandler>();

In the Startup class constructor, inject the HostingEnvironment and store it as a private field. Then in ConfigureServices, check the current environment. If it isn’t development, configure MVC to add the required HTTPS filter as a global filter. That way, it is automatically applied to all controllers. With this configuration in place, we can now debug locally without trouble because everything works with HTTP. And when you deploy it to a web server, the browser will redirect to HTTPS whenever a non-secure HTTP call is attempted.

HTTP Strict Transport Security (HSTS)

Most of the HTTPS enables sites performing the redirection from HTTP to HTTPS when they receive a HTTP request.

Image 1 : Redirect from HTTP to HTTPS

When you do this , it will enable someone to send an insecure first request to a site (bank.com in our example ). For an example, let’s say we’re at a public location, and you are connected to the free WiFi there. Our sneaky man in the middle controls that WiFi router and he has configured it to serve up his version of bank.com whenever a request to bank.com is made.

Image 2 : the HTTP request is intercepted by a middleman

​You can see the correct URL in the browser and enter credentials on the page of the attacker that of course, looks exactly like the real bank.com, after which the attacker quickly logs in into the real bank.com and enters your credentials to transfer money to your own account. This wouldn’t have happened when the initial request was done via SSL because the SSL certificate also issues the origin of the website. To cope with that, you can let your website return this header as part of the very first response the browser gets from your website.

You can specify the HSTS header as follows.

Strict-Transport-Security : max-age=<in milli seconds>

How this header is processed by the browser? The browser will add the website to an internal list and, in the future, no attempts will be made to contact that website again in an insecure manner. It will redirect to HTTPS internally, and it will do that for until the it reaches the max age parameter value. After the max age , the browser will receive the header again and the process start all over again.

This browser feature is called HSTS. Out of the box, there is no real support for HSTS in ASP.NET Core MVC. You will have to write some code to implement it or use the excellent open source framework such as , Nwebsec, which you can install as a NuGet package. It supports not only HSTS, but it features many more security-related things.

Warning :

Once you setup the HSTS, there is no turning back. ie : the browser is always looking for HTTPS channel to reach your site until the it reaches the max age. So if you decide to remove the HTTPS protocol from your site, the browser would not be able to reach your site at all.

But still we cannot 100% guarantee the security of the first request, because the browser cannot get your HSTS header until it finishes the first request. To counter this, you can go to this site and pre load your certificates and configure the HSTS. The browser will pre load the header and secure your first request as well.

if you are using the NwebSec nuget package, you can configure the HSTS in your ASP.Net Core web application using following code.

in the Configure method in the start up class.

app.UseHsts(options=> options.MaxAge(days:200).PreLoad());

Now your site is registered and future updates of the browser will include your site in its HSTS list.

Image 3 : Middleman cannot intercept the request

SQL Injection

SQL Injection attack is standout amongst the most dangerous attacks. It is positioned 1 in top 10 Vulnerabilities by OWASP2013 [Open Web Application Security Project]. SQL injection attack will provide valuable information to the attacker that may result in an enormous security breach and might conjointly take full access to the database server. In SQL Injection, attacker dependable attempt to enter malicious SQL statement which will get executed in the database and return undesirable data to the attacker.

For example, if you have coded an action where the name input comes in as a string.

public student GetStudents(string name)

{

string query = “select * from students where student_name=” + name;

// logic to execute the query and return the student object

}

Because it’s a primitive type, it will be part of URI in a query string. Take that input and paste it into a SQL query which you can then execute. So what if the user input is not what you expect? Where a name is supposed to be with a quote and add an OR with a comparison that is always true. The two dashes indicate to the SQL database that everything that comes next in the query should be treated as a comment.

Some guidelines to prevent SQL injection:

  • Don’t accept the user input as it is. Do the sanitization.
  • Narrow the attack surface by using a least privileged account in the database. So the malicious user wont be able to do harmful thing like deleting a database or table.
  • If you are using an ORM, an Object Relational Mapper like Entity Framework, you are basically covered. Note in all cases though when the ORM calls a stored procedure which concatenates the query in the same way I showed you in the previous light, you still have a vulnerability.

Cross-Site Request Forgery (CSRF)

Cross-site Request Forgery alludes to an attack against approved web applications utilizing cookies wherein an attacker can trap a victim into making a demand the victim did not plan to make. Accordingly, with CSRF an attacker manhandle the trust a web application has with a victim’s browser.

Cross-site Request Forgery (CSRF) is a sort of jumbled delegate attack which utilizes the approval and the validation of the victim when a forged request is being sent to the web server.

Image 4: Middleman intercepting the session and using cookie details

​​After sending an HTTP request, the victim’s browser will incorporate the Cookie header. Cookies are regularly used to store a user’s session identifier keeping in mind the end goal to dodge the user from having to re-verify for each request. If the victim’s verification session is stored in a Cookie which is as yet substantial, and if the application is powerless against Cross-site Request Forgery (CSRF), then the attacker can use CSRF to launch any solicitations requests against the website, without the website having the capacity to verify whether the requests are legitimate or not.

Assuming the original bank request contains two params such as Amount and ReceivingAccountNumber, a malicious web form can contain something like a following form request where it forces user to click the submit button and send the request.

<h1> You have won Rs. 2,000,000 </h1>

<form action= "https://bank.com/api/transfer" method = "post">

<input type = "hidden" name="Amount" value = "10000" />
<input type = "hidden" name="ReceivingAccountNumber" value = "123-232134-23" />

<input type = "submit" value = "Click here to redeem your winning price" />

</form>

In here the malicious web form adds the attacker’s account number into the ReceivingAccountNumber field.

There are two methodologies by which Cross-site Request Forgery (CSRF) might be prevented — synchronizing the cookie with an anti-CSRF token that has just been given to the browser, or preventing the browser from sending cookies to the web application in any case.

Luckly in ASP.Net Core web apps, you can prevent this just adding one annotation to your controller. Just add the [ValidateAntiForgeryToken] annotation into your controller method [HttpPost].

Remember that all cookies, even the mystery ones, will be submitted with every request. All verification tokens will be submitted paying little respect to regardless of whether the end-client was deceived into presenting the request.

I will be publishing next blog very soon and in there we will be discussing the ASP.Net security aspects to prevent Cross Site Scripting , Content Security Policy, Open redirect attack and Click jacking. If you have any query/concern then you can drop me an email on or send me a message on LinkedIn or Twitter. I’m just a message away :)

Thanks for reading !

CTO @ ZorroSign | Seasoned Software Architect | Expertise in AI/ML , Blockchain , Distributed Systems and IoT | Lecturer | Speaker | Blogger