-1

I am looking into Stored Cross-site Scripting vulnerabilities that occur when the data provided by an attacker is saved on the server, and is then displayed upon subsequent requests without proper HTML escaping.
I have NET 5 ASP.NET Core application using MVC. The application is using jQuery and Telerik's ASP.NET Core library. Both use JSON data returned from the server.

The application has several action methods that query stored data in the database and return as JsonResult.

For example, the following action method

[HttpGet]
[Route("items/json/{id}")]
public async Task<ActionResult> GetName([FromRoute] int id)
{
    var i = await _itemService.GetWorkItem(id);
    return Json(new
    {
        ItemName = i.Name
    });
}

and client side script shows the ItemName in html using jQuery

       $.get(url)
          .done(function (response, textStatus, jqXHR) {
              $("#itemname").html(response);
           })

Suppose a user has stored the name as <script>alert('evil');</script> then the code above will execute the evil script on client side.
The application is using Newtonsoft as default serializer. By default the response does not get Html encoded. The response from the server looks like

{"ItemName":"\u003Cscript\u003Ealert(\u0027evil\u0027);\u003C/script\u003E"}

Also setting default JsonSerializerSettings in Startup like below does not work the same way as the Html Encode.

var serializerSettings = new JsonSerializerSettings()
{
    StringEscapeHandling = StringEscapeHandling.EscapeHtml
};

Is there any default way in ASP.NET Core (Net 5) to handle html encoding during JSON serialization?

I understand that there is WebUtility.HtmlEncode() and also HtmlEncoder class available which can be used to apply encoding selectively . I am looking for a solution to handle html encoding by default during the JSON serialization.

Is new System.Text.Json by default applies html encoding on property values?

UPDATE 1
The comments below suggest to configure NewtonsoftJson in startup.cs. Note that question is NOT how to configure newtonsoft globally but how to html encode property value during the serialization so client (Browser) wont execute the malicious script. I have tried Newtonsoft.Json.StringEscapeHandling.EscapeHtml which did not work. The script still executes

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews()
        .AddNewtonsoftJson((options) =>
        {
            options.SerializerSettings.StringEscapeHandling = Newtonsoft.Json.StringEscapeHandling.EscapeHtml;
        });
    }
LP13
  • 30,567
  • 53
  • 217
  • 400
  • Hi @LP13, `JsonSerializerSettings` is used for Newtonsoft.Json. If I use the same settings of `JsonSerializerSettings ` in ASP.NET Core 5.0 together with `services.AddControllersWithViews().AddNewtonsoftJson();`, it works fine. Also it should be `$("#itemname").html(response.itemName);`. And for System.Text.Json it escapes html characters by default, you can see it will alert after ajax call back. – Rena Jul 19 '22 at 02:42
  • Well you are missing the actual question then. To handle Stored Cross-site Scripting issue you have to prevent browser executing the malicious script. For that you have to HTML encode the output. If alert is executing then HTML encoding is not working. Its only doing the JSON encoding – LP13 Jul 19 '22 at 15:39
  • I found what I was looking for https://stackoverflow.com/questions/44115979/automatically-htmlencode-strings-when-the-model-is-serialized-with-json-net – LP13 Jul 21 '22 at 18:18

1 Answers1

-1

You have to use Newtonsoft.Json if you don't want to create tons of code for each quite simple case. This is working for me

      [HttpGet]
     public async Task<ActionResult> MyTest ()
     {        
            return new JsonResult(new
            {
                ItemName = "<script> alert('evil');</script>"
            }); 
        }

and use response.itemName on client side

 $("#itemname").html(response.itemName);

to use Newtonsoft.Json change your startup code to this

using Newtonsoft.Json.Serialization;

services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
  options.SerializerSettings.ContractResolver =
        new CamelCasePropertyNamesContractResolver());
Serge
  • 40,935
  • 4
  • 18
  • 45
  • CamelCasePropertyNamesContractResolver will only change the property name casing to `camelCase` thats it. It will not stop browser executing the script. Server will have to HtmlEncode the property value and that was the question – LP13 Jul 18 '22 at 23:32
  • @LP13 My advise is to AddNewtonsoftJson instead of Text.Json. Camel case is just a free bonus. I always give the full advise, not just a part. – Serge Jul 18 '22 at 23:43
  • question is not how to configure Newtonsoft globally but How to html encode Json response – LP13 Jul 19 '22 at 15:59
  • @LP13 I am sorry , but I am not a professor and I don't understand what you are talking about. I am a software developer and offering the code that was tested and working. Do you need your code working or do you need just to talk? Do you have any problem with this code? – Serge Jul 19 '22 at 16:08