19

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; }

...
Mihir Ajmera
  • 127
  • 1
  • 9
Sha
  • 2,185
  • 1
  • 36
  • 61
  • 1
    AFAIK tinymce automatically protects from XSS, at the very least it offers you a wide range of configurable options. On top of that I would just stripe non-whitelisted tags. A few example of striping/whitelisting the input data [1](https://stackoverflow.com/questions/15216706/server-side-html-filtering-library-in-asp-net-mvc) [2](https://stackoverflow.com/questions/17581936/how-to-sanitize-input-from-mce-in-asp-net) – Prix Sep 08 '18 at 22:19
  • Please look this one: https://stackoverflow.com/questions/37923431/antixss-in-asp-net-core?rq=1 . @Christian Del Bianco has good answer – Basil Kosovan Jul 08 '19 at 11:11
  • Does this answer your question? [AntiXSS in ASP.Net Core](https://stackoverflow.com/questions/37923431/antixss-in-asp-net-core) – Michael Freidgeim May 03 '21 at 22:28

5 Answers5

10

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

JHBonarius
  • 10,824
  • 3
  • 22
  • 41
  • 1
    Thanks for the reply - I have updated my question to be more be more clear. I like the HtmlSanitizer for the frontend part but I am more interested in avoiding malicious data getting into the database. – Sha Sep 08 '18 at 21:40
  • 2
    @Sha You can use HtmlSanitizer in a ResourceFilter to strip out "evil stuff" before hitting your controller, thereby never making it to the database. – Zach J. Nov 05 '19 at 14:29
5

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.

shawkyz1
  • 886
  • 5
  • 19
  • how do you use this technique to prevent xss made from an image data in base64 string? Not sure it works. – Rez.Net Jul 22 '19 at 01:38
  • can you tell me more details? If you're saying that an – shawkyz1 Jul 22 '19 at 11:07
  • The base64 string in my project is the content of an image file (profile photo) uploaded by the user. This base64 data goes straight into src attribute of an img tag, appended some meta data (data:image/png;base64, ). Do you see any chance of xss in here? – Rez.Net Jul 24 '19 at 06:03
5

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.

Zach J.
  • 204
  • 2
  • 7
3

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.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
dougajmcdonald
  • 19,231
  • 12
  • 56
  • 89
  • sounds like exactly case with WYSIWYG controls. People can post all sort of stuff. And as long as I show it back in such control - this is ok. Buit if I show it in html form, this is an issue. – T.S. Feb 03 '20 at 18:03
2

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?

Mihir Ajmera
  • 127
  • 1
  • 9
Andrei Bazanov
  • 352
  • 2
  • 11