Dude, Where’s My Request Validation?
While in the process of migrating our ASP.NET on-demand training course to ASP.NET Core, I noticed ASP.NET Core 1.0 did not include a similar feature to ASP.NET’s Request Validation.
As the server accepts the HTTP request we can see below that an application exception is thrown since Request Validation found the dangerous content. The malicious content never makes it into the application.
Now that you have some familiarity of what the Request Validation does, you can probably see why I have some concerns about ASP.NET web projects being migrated to ASP.NET Core. As the above examples show, if the application only relies on Request Validation for XSS protection, there is a good possibility security vulnerabilities will be introduced into the application by migrating the application to ASP.NET Core.
So why the lack of documentation? From what I can tell there has been minimal, if any notification about Request Validation being excluded from ASP.NET Core to the development community. Request Validation has been a staple of ASP.NET for over a decade. The ASP.NET development community has relied heavily on the feature. So why haven’t we seen more communication?
When I first noticed that ASP.NET Core was not protecting the application from malicious content, I started searching for documentation on ASP.NET Core Request Validation. There were two resources I stumbled upon that helped me. The first being a Stack Overflow question where someone asked, how to enable Request Validation in ASP.NET Core. In the answer to the question the author explains that ASP.NET Core does not have a feature similar to Request Validation. Included in that explanation was a link to the second resource which was a discussion on the ASP.NET Core issue, “Default middleware for request validation, like IIS has”. In that discussion, it is explained that Request Validation will be excluded from ASP.NET Core and the focus for ASP.NET Core will be to encode output by default.
No more Request Validation, now what? Well first off let’s remember the function Request Validation performs in applications. It adds a layer of data validation, which checks for malicious content in the incoming request. So how do we replace the data validation, you ask? If you read the ASP.NET Core issue I referenced above you saw part of the discussion mentions data validation should be performed on the inbound model, not the request.
Not familiar with ASP.NET MVC and the term model? Let me give you a brief explanation of how models are used when data is stored in a database. The model is the class the represents data in the database. Each instance of the model can correspond to a row within a database table, and each property of the model can map to a column in the table. On HTTP Request, posted form values are mapped to the model properties and sent to the action method in the controller. This is where data validation comes into play.
When performing data validation on models I recommend adding Data Annotation attributes to your model classes. In ASP.NET Core the System.ComponentModel.DataAnnotations namespace provides a list of attributes that allows us to describe the rules we want applied to the model class and it’s properties. MVC will handle the enforcing of the rules and display the appropriate messages to the user.
Using the ASP.NET Core example from earlier, let’s explore what Data Annotations give us. First, let’s take a look at the data annotation as they are applied to the model properties. For this example, I used the
RegularExpression attributes to perform some basic data validation. The
DisplayAttribute tells ASP.NET Core what name to display in the view.
ASP.NET Core will create the client-side jQuery validation during the creation of the view. Looking at the below image you will notice client-side validation being performed based on the attribute rules applied to the model properties.
The action method in the controller will check to see if the model state is valid. In this case, the
Message property does not pass the rules assigned to the property. The controller returns the model error message to the web browser where the message is displayed.
As we can see by adding a few attributes to the model properties, the application now has its own layer of validation. Another reason for using Data Annotations is its flexibility. Rules can be placed on the class or you can create your own custom annotations. Keep in mind, since the validation rules are assigned to the model you can validate the model data in any layer of the application.
Data Annotations are great for validating the incoming data, but what about the data that is reflected out to the user’s web browser? If you remember from earlier I mentioned that part of ASP.NET Core issue discussion was about the focus being on ensuring that all output is encoded to the proper context before being sent to the web browser. Let’s take a look at what encoding offers us.
Building on the XSS example from above I changed the rules for the
When defending against XSS, the primary defense should always be output encoding. The Razor view engine makes this easy for developers by providing HTML encoding by default when using
@. For example, the code
@ViewBag.TheMessage was used to display the message in the above screen shot. By utilizing
@ViewBag our content was automatically HTML encoded. However, there is one exception when using the
@HTML.Raw helper method will not provide encoding as it makes the content part of the HTML in the view. If you need to use
@HTML.Raw to display HTML markup, make sure user controlled data is encoded in the proper context before adding it to the HTML helper. The encoding can be achieved by using the ASP.NET Core public static property
Even though Request Validation is gone from ASP.NET Core, we can still protect the application data and our users by implementing data validation and contextual encoding. Now granted if you are using ASP.NET MVC and not ASP.NET Core, it is still good practice to implement data validation and encoding. Also, keep in mind that Data Annotations and encoding are not specific to ASP.NET Core, and are is also available in ASP.NET MVC.
So yes, the beloved Request Validation feature was removed in ASP.NET Core 1.0. Now that we know this let’s get the word out. Development teams need to be aware that a major feature providing a layer of security has been stripped from ASP.NET Core. If you are on a development team making the switch over to ASP.NET Core, keep in mind that while data validation is still possible, the proper mitigation for XSS is contextual encoding. Adding a layer of data validation can add to the security posture of the application, but is designed to enhance user experience and efficiency.