Skip to main content

Stored cross-site scripting (XSS)

Need

Prevention of persistent cross-site scripting (XSS) attacks

Context

  • Usage of C# for building robust and scalable applications
  • Usage of System for low-level operating system interactions and utilities
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core

Description

Non compliant code

using System;
using Microsoft.AspNetCore.Mvc;

namespace VulnerableApp.Controllers
{
public class HomeController : Controller
{
[HttpPost]
public IActionResult Index(string userInput)
{
ViewBag.UserInput = userInput;
return View();
}
}
}

In the provided C# code, we have a simple ASP.NET Core application with a single controller HomeController. This controller has a HttpPost action method Index that accepts a string parameter userInput.

This userInput parameter is directly assigned to ViewBag.UserInput without any sanitization, which means whatever the user submits will be stored directly in ViewBag.UserInput.

In the corresponding Razor view, @Html.Raw(ViewBag.UserInput) is used to render the user input. The @Html.Raw method outputs the unencoded string, which means any HTML or JavaScript code submitted by the user will be rendered directly in the browser.

This is a clear example of a Stored Cross-Site Scripting (XSS) vulnerability because an attacker can submit a JavaScript code as userInput, which will then be stored and rendered every time the page is loaded. This can lead to various harmful scenarios such as session hijacking or distribution of malicious software.

Steps

  • Implement input validation to sanitize user input.
  • Use output encoding to prevent the execution of injected scripts.
  • Implement Content Security Policy (CSP) to restrict the types of content that can be loaded by the application.
  • Educate developers about secure coding practices to prevent future vulnerabilities.

Compliant code

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using System.Text.Encodings.Web;

namespace VulnerableApp.Controllers
{
public class HomeController : Controller
{
private readonly HtmlEncoder _htmlEncoder;

public HomeController(HtmlEncoder htmlEncoder)
{
_htmlEncoder = htmlEncoder;
}

[HttpPost]
public IActionResult Index(string userInput)
{
string encodedInput = _htmlEncoder.Encode(userInput);
ViewBag.UserInput = encodedInput;
return View();
}
}
}

The updated code now includes a constructor for the HomeController that accepts an HtmlEncoder object. This object is used to encode the user input in the Index method.

The HtmlEncoder.Encode method is used to sanitize the user input. This method encodes special characters in the input string to their HTML-encoded equivalents. For example, the < character is encoded as <, the > character is encoded as >, and so on. This prevents any HTML or JavaScript code in the user input from being executed when the input is displayed in a view.

This is a simple and effective way to prevent stored cross-site scripting (XSS) attacks. However, it's important to note that this is just one layer of defense. Other measures, such as implementing a Content Security Policy (CSP) and educating developers about secure coding practices, should also be taken to further enhance the security of the application.

References