July 24, 2020
As security continues to be a major concern in today’s web development landscape, .NET Core provides a solid foundation for building secure applications. However, simply using .NET Core is not enough; developers need to be mindful of the best security practices in order to safeguard their applications against common vulnerabilities.
In this post, we’ll dive into some advanced security practices for Web API and MVC apps built with .NET Core. We’ll specifically focus on how to defend your application against cross-site scripting (XSS), SQL injection, and other critical security threats.
1. Secure Coding Practices for Web API and MVC Apps
Before we jump into specific attacks, it’s important to adopt secure coding practices from the start. Here are a few tips that can go a long way in improving your app’s security:
- Input Validation: Always validate input from users. This includes checking the length, type, and format of user inputs.
- Output Encoding: Encode data before sending it to the browser, especially data that comes from untrusted sources. This helps prevent injection attacks.
- Use HTTPS: Ensure that communication between the client and server happens over HTTPS (SSL/TLS). This prevents man-in-the-middle attacks.
- Authentication and Authorization: Implement strong authentication (OAuth, JWT) and ensure proper authorization checks on every API endpoint or action in MVC controllers.
Now, let’s take a deeper look at how to defend your application against specific attacks.
2. Protection Against Cross-Site Scripting (XSS)
Cross-Site Scripting (XSS) is a type of vulnerability where attackers inject malicious scripts into web pages viewed by other users. These scripts can steal cookies, session data, or perform actions on behalf of the user without their consent.
a. How to Prevent XSS in .NET Core
- Use ASP.NET Core’s built-in HTML encoding: By default, ASP.NET Core MVC uses the Razor view engine, which automatically encodes data to prevent XSS. For example, when rendering user input within an HTML element, Razor automatically encodes it to make sure any script tags are neutralized. Example of Razor View automatically escaping user input:
<h1>@Model.Username</h1>
If Model.Username
contains a script (<script>alert('XSS');</script>
), Razor will output it as text, not as executable code.
- Avoid client-side JavaScript injection: Do not insert untrusted input directly into JavaScript variables. If absolutely necessary, ensure that any JavaScript code is safely encoded or validated. Bad Example (vulnerable to XSS):
var user = '@Model.Username';
alert(user);
Good Example (safe from XSS):
var user = '@Html.Encode(Model.Username)';
alert(user);
- Content Security Policy (CSP): Implement a CSP header in your application to reduce the risk of XSS by specifying which sources of content are allowed. For example, you can restrict your application to only load scripts from your own domain. In ASP.NET Core, you can add the Content-Security-Policy header in your middleware configuration:
public void Configure(IApplicationBuilder app)
{
app.UseCsp(options => options
.BlockAllMixedContent()
.StyleSources(s => s.Self())
.ScriptSources(s => s.Self())
);
}
3. Protection Against SQL Injection
SQL Injection occurs when an attacker is able to inject malicious SQL statements into an input field, which are then executed by your database. This can lead to unauthorized data access, modification, or even deletion.
a. How to Prevent SQL Injection in .NET Core
- Use Parameterized Queries: Always use parameterized queries or ORMs (Object-Relational Mappers) like Entity Framework Core to interact with your database. These tools automatically escape input, which prevents SQL injection. Bad Example (vulnerable to SQL injection):
var query = "SELECT * FROM Users WHERE Username = '" + username + "' AND Password = '" + password + "'";
var result = dbContext.Users.FromSqlRaw(query).ToList();
Good Example (safe from SQL injection):
var query = "SELECT * FROM Users WHERE Username = @username AND Password = @password";
var result = dbContext.Users.FromSqlRaw(query, new SqlParameter("@username", username), new SqlParameter("@password", password)).ToList();
With Entity Framework Core, parameterized queries are automatically used for FromSqlRaw
and ExecuteSqlRaw
, so you don’t need to manually handle the SQL parameters.
- Use ORM (e.g., EF Core): If you’re using Entity Framework Core, SQL injection is generally mitigated because EF Core uses parameterized queries by default. Avoid writing raw SQL unless absolutely necessary.
- Stored Procedures: Another option is to use stored procedures for critical queries, which adds an extra layer of abstraction and reduces the risk of SQL injection.
4. Other Security Best Practices
a. SQL Injection Prevention with Stored Procedures
While parameterized queries are a great defense against SQL injection, stored procedures offer additional layers of abstraction. You can define queries once in the database, and only allow certain actions or operations to be executed from your application.
b. Security Headers
For added protection, make sure to configure various HTTP security headers such as:
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY (prevents clickjacking)
- Strict-Transport-Security (forces HTTPS)
- Referrer-Policy (controls what information is sent in the referrer header)
In ASP.NET Core, you can add these headers via middleware:
public void Configure(IApplicationBuilder app)
{
app.UseXContentTypeOptions();
app.UseXfo(options => options.Deny());
app.UseStrictTransportSecurity(TimeSpan.FromDays(365));
app.UseReferrerPolicy(opts => opts.NoReferrer());
}
5. Conclusion
Securing your .NET Core applications is not an afterthought—it’s a critical part of the development process. By following these advanced security practices, such as using parameterized queries, encoding output, and applying security headers, you can protect your application against common vulnerabilities like XSS and SQL injection.
Security is a constantly evolving field, so always keep your dependencies up to date and be aware of new vulnerabilities and mitigation techniques. Implementing strong security practices in your Web API and MVC applications will go a long way in safeguarding both your data and your users.
Stay vigilant and keep coding securely!