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.
To protect most from XSS vulnerabilities, follow three practices: Escape user input. Escaping means to convert the key characters in the data that a web page receives to prevent the data from being interpreted in any malicious way. It doesn't allow the special characters to be rendered.
Web application firewall. A web application firewall (WAF) can be a powerful tool for protecting against XSS attacks. WAFs can filter bots and other malicious activity that may indicate an attack. Attacks can then be blocked before any script is executed.
Using htmlspecialchars() function – The htmlspecialchars() function converts special characters to HTML entities. For a majority of web-apps, we can use this method and this is one of the most popular methods to prevent XSS. This process is also known as HTML Escaping.
Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user.
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" />
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With