Skip to main content

Server side cross-site scripting

Need

Mitigation of server-side cross-site scripting attacks

Context

  • Usage of C# for building robust and scalable applications
  • Usage of Microsoft.AspNetCore.Mvc for building web applications using the MVC pattern in .NET Core
  • Usage of Microsoft.Extensions.Logging for logging and diagnostics in .NET applications

Description

Non compliant code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace VulnerableApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class VulnerableController : ControllerBase
{
private readonly ILogger<VulnerableController> _logger;

public VulnerableController(ILogger<VulnerableController> logger)
{
_logger = logger;
}

[HttpGet]
public string Get(string input)
{
return "You entered: " + input;
}
}
}

In this code, we have a controller named VulnerableController with a GET method that accepts a string parameter input. The method returns a string that includes the user input.

This is a typical example of Unvalidated Input, a common web application vulnerability. In this case, the server does not validate, filter, or sanitize the input before including it in the output.

If an attacker provides a string that includes JavaScript code as the input, the server will include this script in the response. When this response is rendered by a web browser, the script will execute. This is a form of Cross-Site Scripting (XSS) known as Server-Side XSS.

For example, an attacker might enter a string like "<script>malicious code here</script>". The server would then return "You entered: <script>malicious code here</script>". When this string is rendered by a web browser, the malicious script will execute.

This vulnerability can lead to serious issues like session hijacking, identity theft, defacement of the website, and other security breaches.

Steps

  • Implement input validation to sanitize user input
  • Encode user input before rendering it in the response
  • Use a Content Security Policy (CSP) to restrict the execution of inline scripts
  • Implement output encoding to prevent script injection

Compliant code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using System.Text.Encodings.Web;

namespace VulnerableApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class VulnerableController : ControllerBase
{
private readonly ILogger<VulnerableController> _logger;
private readonly HtmlEncoder _htmlEncoder;

public VulnerableController(ILogger<VulnerableController> logger, HtmlEncoder htmlEncoder)
{
_logger = logger;
_htmlEncoder = htmlEncoder;
}

[HttpGet]
public string Get(string input)
{
var encodedInput = _htmlEncoder.Encode(input);
return "You entered: " + encodedInput;
}
}
}

The code above is a fixed version of the vulnerable code. The vulnerability was a server-side cross-site scripting (XSS) vulnerability, which allowed an attacker to inject JavaScript into application fields. This could lead to the server executing malicious code before rendering user input.

To fix this vulnerability, several steps were taken:

  1. Input Validation: The application now sanitizes user input. This is done by encoding the user input using the HtmlEncoder class provided by ASP.NET Core. This class encodes special characters in the input string to their HTML-encoded equivalent. For example, &lt; becomes &lt;, > becomes &gt;, and " becomes &quot;. This prevents any HTML or JavaScript code in the input from being executed.

  2. Output Encoding: The application now encodes user input before rendering it in the response. This is done by using the HtmlEncoder.Encode method on the user input. This ensures that any HTML or JavaScript code in the input is displayed as plain text in the response, rather than being executed.

  3. Content Security Policy (CSP): Although not shown in the code, it is recommended to implement a CSP to restrict the execution of inline scripts. This can be done by adding a Content-Security-Policy header to the HTTP response with a value that disallows inline scripts. For example, Content-Security-Policy: script-src 'self'.

By implementing these steps, the application is now protected against server-side XSS attacks.

References