How to protect against XSS in ASP.NET Core? - c#

In ASP.NET we had Request Validation but in ASP.NET Core there is no such thing.
How can we protect an ASP.NET Core app against XSS in the best way?
Request validation gone:
https://nvisium.com/resources/blog/2017/08/08/dude-wheres-my-request-validation.html
this guy recommmends RegEx on Models like:
[RegularExpression(#"^[a-zA-Z0-9 -']*$", ErrorMessage = "Invalid characters detected")]
public string Name { get; set; }
...but that does not work for globalization/internationalization, i.e. non-latin characters like æ, ø å 汉字.
X-XSS to do >limited< XSS-protection: https://dotnetcoretutorials.com/2017/01/10/set-x-xss-protection-asp-net-core/ Like this but there is only limited support afaik:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Xss-Protection", "1");
await next();
});
app.UseMvc();
}
The documentation from Microsoft is two years old: https://learn.microsoft.com/en-us/aspnet/core/security/cross-site-scripting?view=aspnetcore-2.1 and does not really cover it.
I am thinking to do something simple like:
myField = myField.Replace('<','').Replace('>','').Replace('&','').Repl...;
on all data submission - but it seems kind of wonky.
I have asked the same question for Microsoft but I am interested to hear how people are solving this problem in real-life applications.
Update: what we are trying to accomplish:
In our application, we have webforms where people can input names, email, content and similar. The data is stored in a database and will be viewed on a frontend system and possibly other systems in the future (like RSS feeds, JSON, whatever). Some forms contain rich-text editors (TinyMCE) and allow users to markup their texts. Malicious users could enter <script>alert('evil stuff');</script> in the fields. What is the best way to strip the evil characters in ASP.NET Core before it reaches the database - I prefer evil scripts not to be stored in the database at all.
I figured something like this could work:
const string RegExInvalidCharacters = #"[^&<>\""'/]*$";
[RegularExpression(RegExInvalidCharacters, ErrorMessage = "InvalidCharacters")]
public string Name { get; set; }
[RegularExpression(RegExInvalidCharacters, ErrorMessage = "InvalidCharacters")]
public string Content { get; set; }
...

You can use the HtmlSanitizer NuGet package in ASP.NET Core.

One of the best ways in preventing stored/reflected XSS is to HTML-Encode the output. You may also encode before you store it in the DB.
Since you don't need the output from these fields to be in HTML anyways.
The solution with the Regex won't always work. What you're doing here is that you are relying on a blacklist. It's always better and more secure to either rely on Whitelist (Which you don't need in this case). Or HTML-Encode the output if possible.

I know this is a year old now, but for your (and others') reference, you may want to look at creating a ResourceFilter or Middleware which will sanitize incoming requests. You can use whatever tools or custom code you want there, but the key being that all incoming requests go through this filter to be sanitized of bad data.
Be sure to use the correct filter for your application/need. A ResourceFilter will run before model binding, and an ActionFilter will run after model binding.

Specifically, what are you trying to do here? Prevent posts which could contain content which could render, when un-sanitised an XSS attack?
If so, as I recently discussed with a colleague, you kind of can't, depending on your site.
You can provide client-side restrictions on the data posted, but this can obviously be bypassed, so what's your action trying to do? Prevent content being posted that when rendered un-sanitised is a potential XSS risk?
What is your post endpoint responsible for? Is it responsible for how other systems may render some output it has received?
I would argue your main XSS risk is in how an app renders your data. If you're not sanitising/encoding output based on the app that is using the data then you're probably doing it wrong.
Remember that a potential XSS issue is only a real issue if you're outputting something to a webpage or similar. This is not really the endpoint that receives the data's problem.

I know this has been answered already, and quite adequately, but I want to add my answer as a way of getting some feedback as well. This is what I have done in this case, which is very similar to the question at hand.
Scenario
We have a front-end application built in Vue.js wrapped in "Quasar.dev", which is being served by a .NET 5.0 API on the back side.
Solution
We have "public models" which are objects we use to send to the client application. They are not named and formatted as their database fields. We use "AutoMapper" to map from database fields (or models) to public fields (or models) Once the public model has been mapped we then send the public model to the user. Then inside the AutoMapper profile, I added an extension to the String object called .Encode() which encodes whatever comes from the database into the public model field using the following code...
public static string Encoded(this string value)
{
return HttpUtility.HtmlEncode(value);
}
Now, every time I add new profiles for public models, I just make sure to add that call for encoding on strings I do not trust.
How about that?

Related

Asp.net mvc: an object reference is required Error while calling a function in [Required(ErrorMessage)

I am creating a web app in asp.net-mvc in which I am sending a Required ErrorMessage from my model, but the problem is, I want to translate the message as per user's preference,
so I did something like below
[Required(ErrorMessage = convertErrorMessage("Text to translate"))]
public string Reviews { get; set; }
public string convertErrorMessage(string text)
{
//convertingText in different language
return convertedText;
}
but I am getting the below error
an object reference is required for non static field
on the below line
[Required(ErrorMessage = convertErrorMessage("Text to translate"))]
what can I do, if I want to achieve this?
You cannot call methods to initialize attributes, because these values have to be known at compile time. There are two possible other ways though:
ASP.NET MVC supports standard ways to doing localization, which is the recommended way to go. It is a very broad topic, so I can only leave a few links [1], [2] here. Notice that even the RequiredAttribute you are using has properties ErrorMessageResourceName and ErrorMessageResourceType - these are strong hints that you should be using standard tooling for standard tasks.
If you still want to stick to what you have, define your own attribute and implement your custom logic in there:
class RequiredLocalizedAttribute : RequiredAttribute {
// override ErrorMessage get
// or ErrorMessageString get
}
However, I would strongly advise looking into option 1 instead. You may need a bit more time to learn and implement this, and that won't be time wasted, and may save you lots of headache as you application grows

How to warn the user during form input in ASP.NET Core MVC

The user sometimes should be warned about an input but the input is not technically invalid.
I want to implement something like this:
[Range(5, 2147483647, "It's best if you enter a lower number")]
public int duration { get; set;}
PS - I have seen this How to provide warnings during validation in ASP.NET MVC?
but I don't really understand it.
If you want to do it during form input- without posting the form back, you should use Javascript for the task, not C#.
Your Range attribute only works in backend code.
You can use some ready to use javascript libraries. For example jqueryvalidation

User-Agent in mvc 5 application

I Have a MVC 5 application whose back-end is web API. For each request to my server I need to provide user-agent which I can get in controller action method like var UserAgent = Request.UserAgent.ToString(); and pass subsequently in other class like (Controller => Service => HttpRequester => XXXHttpClient) and finally use in actual request in XXXHttpClient class but I think there could be a better way to achieve the same. I tried to google it but didn't find anything relevant so can anyone guide me what would be the best practice If I want to get user-agent directly in XXXHttpClient class instead of passing subsequently.
Little bit of a broad question with a lot of possible answers.
Passing the data through all the layers is usually not a good thing.
What I would do is make an MVC action filter that grabs the user agent and sets it to an object. The object class could be like this:
public class RequestContext
{
public string UserAgent { get; set; }
}
Use your dependency injection framework to inject this once-per-request. Then the action filter and the layer that depends on the data would use the same instance, allowing you to get the data to any layer that needs it.
Another option which uses a static property:
HttpContext.Current.Request.UserAgent
Greater performance, easier to read, but lower testability :)

Correcting user input in ASP.NET MVC4

Background
We've been migrating a large amount of legacy code & systems to ASP.NET MVC forms. I've already coded up a number of CRUD type interfaces with MVC 4, using model binding, validation, attributes etc., so I'm fairly familiar with that whole paradigm. So far, all of these forms have been on our backend administration & management applications, where it pays to have very strict input validation. We are launching our first consumer facing application in MVC and are faced with a different type of problem.
The Problem
Our legacy forms in this area are the main revenue engine for our company. Usability of the consumer experience is the rule of the day. To that end, we want our forms to be as lenient as possible - the legacy system did a number of things to automatically correct user input (in entirely custom, non standard ways each time, of course). To that end, we don't so much want input validation as we want sanitation.
Examples
We ask the user for numerical inputs which have a unit of measure implied. Common ones are currency amounts or square footage. The input label is clear that they don't need to provide these formats:
What is the approximate square footage? (example: 2000)
What is your budget? (example: 150)
People being people, not everyone follows the directions, and we frequently get answers like:
approx 2100
1500 sq. ft.
$47.50, give or take
(Okay, I exaggerate on the last one.) The model that we are ultimately storing into our business logic accepts numeric input type for these fields (e.g. int & float). We can of course use datatype validator attributes (example [DataType(DataType.Currency)] for the budget input, or just having the field type be an integer for the square footage) to clearly indicate to the user they are doing it wrong, providing helpful error messages such as:
The square footage must be numbers only.
A better user experience, however, would be to attempt to interpret their response as leniently as possible, so they may complete the form with as little interruption as possible. (Note we have an extensive customer service side who can sort out mistakes on our system afterwards, but we have to get the user to complete the form before we can make contact.) For the square footage examples above, that would just mean stripping out non-digit characters. For the budget, it would mean stripping out everything that's not a digit or a decimal point. Only then would we apply the rest of the validation (is a number, greater than 0, less than 50000 etc.)
We're stuck on the best approach to take to accomplish this.
Potential Solutions
We've considered custom attributes, custom model bindings, and a separate scrubber service class that would live between the model and the database. Here are some of the considerations we've taken into account trying to decide upon the approach.
Custom Validation Attributes
I've read a number of helpful resources on this. (They have varying degrees of relevancy and recency. A lot of stuff I found searching for this was written for MVC2 or MVC3 and is available with standard attributes in MVC4.)
Extending ASP.NET MVC’s Validation
Custom Validation Attribute in ASP.NET MVC3
A lot of questions & topics on input sanitization which were focused on Cross-site scripting attacks or database injection.
What I haven't found is anyone doing what I want to do, which would be changing the model value itself. I could obviously create a local copy of the value, sanitize it and provide a pass/fail, but this would result in a lot of duplicate code. I would still have to sanitize any input values again before saving to the database.
Changing the model value itself has 3 benefits:
It affects subsequent validation rules, which would improve their acceptance rate.
The value is closer to what will be put into the database, reducing the additional prep & mapping overhead needed before storage.
In the event of the form being rejected for another reason, it gently suggests to the user "You're trying to hard on these fields."
Is this a valid approach? Is there someone out there who has used validation attributes in this way that I just missed?
Custom Model Binding
I read Splitting DateTime - Unit Testing ASP.NET MVC Custom Model Binders which focuses on custom date time input fields with custom validation & parsing done at the model binding layer. This lives a lot closer to the model itself, so it seems like a more appropriate place to be modifying the model values. In fact, the example class DateAndTimeModelBinder : IModelBinder does exactly that in a few places.
However, the controller action signature provided for this example does not make use of an overall model class. It looks like this
public ActionResult Edit(int id,
[DateAndTime("year", "mo", "day", "hh","mm","secondsorhwatever")]
DateTime foo) {
Rather than this
public ActionResult Edit(
MyModelWithADateTimeProperty model) {
Shortly before that, the article does say
First, usage. You can either put this Custom Model Binder in charge of all your DateTimes by registering it in the Global.asax:
ModelBinders.Binders[typeof(DateTime)] =
new DateAndTimeModelBinder() { Date = "Date", Time = "Time" };
Would that be sufficient to invoke the model binding for the date time field on the single-parameter model example MyModelWithADateTimeProperty?
The other potential draw back that I see here is that the model binder operates on a type, rather than an attribute you can apply to the standard data types. So for example, each set of validation rules I wanted to apply would necessitate a new, custom type. This isn't necessarily bad, but it could get messy and cause a lot of repeated code. Imagine:
public class MyDataModel {
[Required]
public CurrencyType BudgetRange { get; set; }
public PositiveOnlyCurrencyType PaymentAmount { get; set; }
[Required]
public StripNonDigitsIntegerType SquareFootage { get; set; }
Not the ugliest model code I've ever seen, but not the prettiest either.
Custom, External scrubber class
This has the fewest questions for me, but it has the most drawbacks as well. I've done a few things like this before, only to really regret it for one of the following reasons:
Being separate from the controller and model, it is nigh impossible to elegantly extend its validation rules to the client side.
It thoroughly obfuscates what is and what isn't an acceptable input for the different model fields.
It creates some very cumbersome hoops for displaying errors back to the user. You have to pass in your model state to the scrubber service, which makes your scrubber service uniquely tied to the MVC framework. OR you have to make your scrubber service capable of returning errors in a format that the controller can digest, which is rather more logic than is usually recommended for a controller.
The Question
Which approach would you take (or, have you taken) to accomplish this type of sanitization? What problems did it solve for you? What problems did you run into?
I would take ModelBinder approach.
When form data comes in - it goes to model binders infrastructure. There you can override decimal model binder to refine input. After that you can send it to validation routines without neeed to write specific validation attributes or something like that.
Also you can use one intelligent model binder that will do type switch internaly or override ModelBinderProvider, so your code wont be bloated with ModelBinderAttribute. Here is Jimmy Bogart article about this. Also you will get some flexibility, because you can use attributes to declare if model uses strict or adaptive binding.
In overall, IMHO, validation attributes are not suposed to alter input. They should validate it. Model binders are in fact responsible for converting all weird stuff that comes in into something usable in your system and your third approach duplicates Model binder functionality)
Hope this helps and sorry for my english)

With MVC, asp.net, is it possible to create a row with URL Query String?

For instance, I'd like to be able to send my.url/movie?title="a"&rating="b" and create a new row in the movie table with the appropriate data.
Is this possible?
One method I've attempted is creating movie.aspx which has movie.aspx.cs and movie.cs as well which can parse the information. Could I then send a post request with the relevant information, maybe?
I'm incredibly new to asp.net, mvc, and c#.
Certainly, in the controller that is fired with the example URL, build a handler for Movie that looks like this:
public ActionResult Movie(string title, string rating)
{
// do your work here
return View("SomeViewHere");
}
where SomeViewHere is the view you want to redirect to when you're done.
You can do this as Michael Perrenoud mentions, but I would strongly recommend against it. This opens you up to all kinds of attacks, including memory attacks where a malicious user could just hit permutations of words in your URL to pollute your database with millions and millions of rows in an effort to make it crash due to running out of space. I would highly recommend against this in any public-facing environment.

Categories

Resources