[java] XSS prevention in JSP/Servlet web application

How can I prevent XSS attacks in a JSP/Servlet web application?

This question is related to java security jsp servlets xss

The answer is


My personal opinion is that you should avoid using JSP/ASP/PHP/etc pages. Instead output to an API similar to SAX (only designed for calling rather than handling). That way there is a single layer that has to create well formed output.


The how-to-prevent-xss has been asked several times. You will find a lot of information in StackOverflow. Also, OWASP website has an XSS prevention cheat sheet that you should go through.

On the libraries to use, OWASP's ESAPI library has a java flavour. You should try that out. Besides that, every framework that you use has some protection against XSS. Again, OWASP website has information on most popular frameworks, so I would recommend going through their site.


If you want to automatically escape all JSP variables without having to explicitly wrap each variable, you can use an EL resolver as detailed here with full source and an example (JSP 2.0 or newer), and discussed in more detail here:

For example, by using the above mentioned EL resolver, your JSP code will remain like so, but each variable will be automatically escaped by the resolver

...
<c:forEach items="${orders}" var="item">
  <p>${item.name}</p>
  <p>${item.price}</p>
  <p>${item.description}</p>
</c:forEach>
...

If you want to force escaping by default in Spring, you could consider this as well, but it doesn't escape EL expressions, just tag output, I think:

http://forum.springsource.org/showthread.php?61418-Spring-cross-site-scripting&p=205646#post205646

Note: Another approach to EL escaping that uses XSL transformations to preprocess JSP files can be found here:

http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/


I would suggest regularly testing for vulnerabilities using an automated tool, and fixing whatever it finds. It's a lot easier to suggest a library to help with a specific vulnerability then for all XSS attacks in general.

Skipfish is an open source tool from Google that I've been investigating: it finds quite a lot of stuff, and seems worth using.


There is no easy, out of the box solution against XSS. The OWASP ESAPI API has some support for the escaping that is very usefull, and they have tag libraries.

My approach was to basically to extend the stuts 2 tags in following ways.

  1. Modify s:property tag so it can take extra attributes stating what sort of escaping is required (escapeHtmlAttribute="true" etc.). This involves creating a new Property and PropertyTag classes. The Property class uses OWASP ESAPI api for the escaping.
  2. Change freemarker templates to use the new version of s:property and set the escaping.

If you didn't want to modify the classes in step 1, another approach would be to import the ESAPI tags into the freemarker templates and escape as needed. Then if you need to use a s:property tag in your JSP, wrap it with and ESAPI tag.

I have written a more detailed explanation here.

http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/

I agree escaping inputs is not ideal.


Managing XSS requires multiple validations, data from the client side.

  1. Input Validations (form validation) on the Server side. There are multiple ways of going about it. You can try JSR 303 bean validation(hibernate validator), or ESAPI Input Validation framework. Though I've not tried it myself (yet), there is an annotation that checks for safe html (@SafeHtml). You could in fact use Hibernate validator with Spring MVC for bean validations -> Ref
  2. Escaping URL requests - For all your HTTP requests, use some sort of XSS filter. I've used the following for our web app and it takes care of cleaning up the HTTP URL request - http://www.servletsuite.com/servlets/xssflt.htm
  3. Escaping data/html returned to the client (look above at @BalusC explanation).

I had great luck with OWASP Anti-Samy and an AspectJ advisor on all my Spring Controllers that blocks XSS from getting in.

public class UserInputSanitizer {

    private static Policy policy;
    private static AntiSamy antiSamy;

    private static AntiSamy getAntiSamy() throws PolicyException  {
        if (antiSamy == null) {
            policy = getPolicy("evocatus-default");
            antiSamy = new AntiSamy();
        }
        return antiSamy;

    }

    public static String sanitize(String input) {
        CleanResults cr;
        try {
            cr = getAntiSamy().scan(input, policy);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return cr.getCleanHTML();
    }

    private static Policy getPolicy(String name) throws PolicyException {
        Policy policy = 
            Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml"));
        return policy;
    }

}

You can get the AspectJ advisor from the this stackoverflow post

I think this is a better approach then c:out particular if you do a lot of javascript.


If you want to make sure that your $ operator does not suffer from XSS hack you can implement ServletContextListener and do some checks there.

The complete solution at: http://pukkaone.github.io/2011/01/03/jsp-cross-site-scripting-elresolver.html

@WebListener
public class EscapeXmlELResolverListener implements ServletContextListener {
    private static final Logger LOG = LoggerFactory.getLogger(EscapeXmlELResolverListener.class);


    @Override
    public void contextInitialized(ServletContextEvent event) {
        LOG.info("EscapeXmlELResolverListener initialized ...");        
        JspFactory.getDefaultFactory()
                .getJspApplicationContext(event.getServletContext())
                .addELResolver(new EscapeXmlELResolver());

    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        LOG.info("EscapeXmlELResolverListener destroyed");
    }


    /**
     * {@link ELResolver} which escapes XML in String values.
     */
    public class EscapeXmlELResolver extends ELResolver {

        private ThreadLocal<Boolean> excludeMe = new ThreadLocal<Boolean>() {
            @Override
            protected Boolean initialValue() {
                return Boolean.FALSE;
            }
        };

        @Override
        public Object getValue(ELContext context, Object base, Object property) {

            try {
                    if (excludeMe.get()) {
                        return null;
                    }

                    // This resolver is in the original resolver chain. To prevent
                    // infinite recursion, set a flag to prevent this resolver from
                    // invoking the original resolver chain again when its turn in the
                    // chain comes around.
                    excludeMe.set(Boolean.TRUE);
                    Object value = context.getELResolver().getValue(
                            context, base, property);

                    if (value instanceof String) {
                        value = StringEscapeUtils.escapeHtml4((String) value);
                    }
                    return value;
            } finally {
                excludeMe.remove();
            }
        }

        @Override
        public Class<?> getCommonPropertyType(ELContext context, Object base) {
            return null;
        }

        @Override
        public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base){
            return null;
        }

        @Override
        public Class<?> getType(ELContext context, Object base, Object property) {
            return null;
        }

        @Override
        public boolean isReadOnly(ELContext context, Object base, Object property) {
            return true;
        }

        @Override
        public void setValue(ELContext context, Object base, Object property, Object value){
            throw new UnsupportedOperationException();
        }

    }

}

Again: This only guards the $. Please also see other answers.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to security

Monitoring the Full Disclosure mailinglist Two Page Login with Spring Security 3.2.x How to prevent a browser from storing passwords JWT authentication for ASP.NET Web API How to use a client certificate to authenticate and authorize in a Web API Disable-web-security in Chrome 48+ When you use 'badidea' or 'thisisunsafe' to bypass a Chrome certificate/HSTS error, does it only apply for the current site? How does Content Security Policy (CSP) work? How to prevent Screen Capture in Android Default SecurityProtocol in .NET 4.5

Examples related to jsp

Difference between request.getSession() and request.getSession(true) A child container failed during start java.util.concurrent.ExecutionException The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path Using if-else in JSP Passing parameters from jsp to Spring Controller method how to fix Cannot call sendRedirect() after the response has been committed? How to include js and CSS in JSP with spring MVC How to create an alert message in jsp page after submit process is complete getting error HTTP Status 405 - HTTP method GET is not supported by this URL but not used `get` ever? How to pass the values from one jsp page to another jsp without submit button?

Examples related to servlets

Google Recaptcha v3 example demo Difference between request.getSession() and request.getSession(true) init-param and context-param java.lang.NoClassDefFoundError: org/json/JSONObject how to fix Cannot call sendRedirect() after the response has been committed? getting error HTTP Status 405 - HTTP method GET is not supported by this URL but not used `get` ever? Create a simple Login page using eclipse and mysql Spring get current ApplicationContext insert data into database using servlet and jsp in eclipse What is WEB-INF used for in a Java EE web application?

Examples related to xss

WARNING: sanitizing unsafe style value url What is the http-header "X-XSS-Protection"? How to pass parameters to a Script tag? How do you use window.postMessage across domains? Sanitizing user input before adding it to the DOM in Javascript XSS prevention in JSP/Servlet web application How do I prevent people from doing XSS in Spring MVC? How to prevent XSS with HTML/PHP? XSS filtering function in PHP Java Best Practices to Prevent Cross Site Scripting