Cross-Site Scripting (XSS) is a web security vulnerability by which a malicious user is able to inject content into a web page that will impact other website visitors. The injected content could then perform any number of unwarranted acts, including hijacking the user’s session, stealing private information, or performing a denial-of-service attack. An XSS exploit often involves manipulating an online form that presents some piece of the input back to the user, such as a search form. In this post we’ll explore some strategies to assist developers with mitigating XSS vulnerabilities, including input validation, sanitation, and output encoding.
- Expecting a numeric identifier? Try converting the value to a number. Check that it is within the expected range (e.g. non-negative, non-zero)
- Is the value expected to be one out of a few possible values, such as with a checkbox list? Verify that the selected value(s) are in fact among of the possible options.
- Need to accept HTML from the user? Sanitize the input by ensuring that any <script> tags and other potentially malicious code is removed.
Mitigating XSS with ASP.NETWe’ll be looking at some specific strategies for mitigating XSS utilizing ASP.NET – both the WebForms and MVC frameworks. These strategies include validation, output encoding, and sanitation.
ASP.NET Input ValidationBy default, ASP.NET applications throw an HttpRequestValidationException in the event that HTML (or other potentially malicious values) are detected in the user input, which terminates the request. Of course, such a blanket strategy can’t cover every possible case – further validation will be needed to ensure that input matches expectations. Additionally, some applications need to be able to work with HTML, such as Web Content Management Systems (CMS). In these cases, the CMS may disable this validation option entirely – even for other pages in the application. It is important to keep this in mind when implementing custom functionality on a CMS-based website. Besides disabling the request validation option globally, there are several options for temporarily lifting validation for specific needs. WebForms pages have a ValidateRequest attribute that can be set to “false”, and MVC controller actions can be decorated with a [ValidateInput(false)] attribute. Individual MVC view model properties can also be decorated with [AllowHtml] for granular control. By opening only specific pages or components of pages that need to allow HTML the developer can ensure that the remainder of the application continues to benefit from built-in validation. In addition to the built-in validation logic, the application itself should validate specific values to ensure they meet expectations. Let’s look at a brief example of resolving an XSS vulnerability. Consider the following method:The code does several things well:
- Ensures the query string values are not null.
- Converts one parameter to a static type - integer (although, it does not do so safely).
- Since the “ContentTypeId” parameter is not safely converted to an integer, the possibility exists for a runtime exception to be thrown, which in turn could show an attacker valuable information such as a stack trace.
- The parameter “ContentId” is not sanitized, and as such this code is vulnerable to an XSS attack.