How do I prevent people from doing XSS in Spring MVC?

109,486

Solution 1

In Spring you can escape the html from JSP pages generated by <form> tags. This closes off a lot avenues for XSS attacks, and can be done automatically in three ways:

For the entire application in the web.xml file:

<context-param>
    <param-name>defaultHtmlEscape</param-name>
    <param-value>true</param-value>
</context-param>

For all forms on a given page in the file itself:

<spring:htmlEscape defaultHtmlEscape="true" /> 

For each form:

<form:input path="someFormField" htmlEscape="true" /> 

Solution 2

I use Hibernate Validator via @Valid for all input objects (binding and @RequestBody json, see https://dzone.com/articles/spring-31-valid-requestbody). So @org.hibernate.validator.constraints.SafeHtml is a good solution for me.

Hibernate SafeHtmlValidator depends on org.jsoup, so it's needed to add one more project dependencies:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.10.1</version>
</dependency>

For bean User with field

@NotEmpty
@SafeHtml
protected String name;

for update attempt with value <script>alert(123)</script> in controller

@PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
public void update(@Valid @RequestBody User user, @PathVariable("id") int id) 

or

@PostMapping
public void createOrUpdate(@Valid User user) {

is thrown BindException for binding and MethodArgumentNotValidException for @RequestBody with default message:

name may have unsafe html content

Validator works as well for binding, as before persisting. Apps could be tested at http://topjava.herokuapp.com/

UPDATE: see also comment from @GuyT

CVE-2019-10219 and status of @SafeHtml

We have been made aware of a CVE-2019-10219 related to the @SafeHtml constraint and it was fixed in both 6.0.18.Final and 6.1.0.Final....

However, we came to the conclusion that the @SafeHtml constraint was fragile, highly security-sensitive and depending on an external library that wasn’t designed for this purpose. Having it included in core Hibernate Validator was not a very good idea. That’s why we deprecated it and marked it for removal.There is no magic plan here so our users will have to maintain this constraint themselves

Resume for myself: it is safe and could be used, until solution better be found.

UPDATE: due to remove @SafeHtml/SafeHtmlValidator from hibernate.validator use own NoHtmlValidator, see https://stackoverflow.com/a/68888601/548473

Solution 3

Try XSSFilter.

Solution 4

When you are trying to prevent XSS, it's important to think of the context. As an example how and what to escape is very different if you are ouputting data inside a variable in a javascript snippet as opposed to outputting data in an HTML tag or an HTML attribute.

I have an example of this here: http://erlend.oftedal.no/blog/?blogid=91

Also checkout the OWASP XSS Prevention Cheat Sheet: http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

So the short answer is, make sure you escape output like suggested by Tendayi Mawushe, but take special care when you are outputting data in HTML attributes or javascript.

Share:
109,486
Doug
Author by

Doug

Updated on July 08, 2022

Comments

  • Doug
    Doug almost 2 years

    What should I do to prevent XSS in Spring MVC? Right now I am just putting all places where I output user text into JSTL <c:out> tags or fn:escapeXml() functions, but this seems error prone as I might miss a place.

    Is there an easy systematic way to prevent this? Maybe like a filter or something? I'm collecting input by specifying @RequestParam parameters on my controller methods.

  • Doug
    Doug about 14 years
    I put <spring:htmlEscape defaultHtmlEscape="true" /> in an include file that I include in all my pages, but it doesn't seem to make a difference. Will that tag cause ${param.q} to be escaped?
  • Andreas
    Andreas almost 14 years
    If you use the resulting strings inside a HTML attribute or a Javascript, defaultHTMLEscape is not enough, then use the <c:out />-tag. It seems like defaultHtmlEscape does not escape all html-characters. It escapes e.g. '<' '>' or '&' but double quotation marks " were not escaped for me. This can lead to problems if the resulting string is used e.g. in a html-attribute or a javascript. (See also answer by Erlend)
  • Andreas
    Andreas almost 14 years
    "take special care" = use the <c:out />-tag when you output data in HTML attributes or javascript. (see my comment at Tendayi Mawushe's answer)
  • Erlend
    Erlend almost 14 years
    Well, it's more than just using <c:out />. Javascript has other control characters than HTML, and can be attacked in different ways, and so needs to be handled using other types of escaping. A simple example:var a = '<c:out ... />'; var b = '<c:out ... />'; If the input in a is a single backslash, script in b will run. Escaping depends on context.
  • Manish Mahajan
    Manish Mahajan about 10 years
    My application stopped working after configuring for xssflt.jar. As soon as i removed filter and filter mapping from web xml it started working.
  • Jack
    Jack over 8 years
    I add the context-param to my web.xml but it does not work.
  • Jack
    Jack over 8 years
    How can I use this in a Maven based project?
  • pinkpanther
    pinkpanther almost 8 years
    Is it for input encoding or output escaping?
  • Dhanu K
    Dhanu K almost 6 years
    it’s not working for form type multipart that means when we sending files with form this filtering is not working, is my query correct? If yes, is there any solution? Or what’s wrong with me
  • SPoint
    SPoint over 5 years
    your code is a bad pattern to avoid XSS. You don't need to do à Blacklist with replace approach. You need to encode output to really fight XSS !
  • GabiM
    GabiM about 5 years
    Blacklisting your input like presented in this answer, as @SPoint also said, is a bad approach. You need a two pronged solution: 1 escape out put and 2 whitelist input. Whitelisting restricts what the user is allowed to submit as opposed to blacklisting where you allow anything and hope to clean the input yourself
  • GuyT
    GuyT about 4 years
    Please note this is deprecated now due to security issues stackoverflow.com/questions/58913428/…