AppSec Blog

AppSec Blog

Seven Security (Mis)Configurations in Java web.xml Files

There are a lot of articles about configuring authentication and authorization in Java web.xml files. Instead of rehashing how to configure roles, protect web resources, and set up different types of authentication let's look at some of the most common security misconfigurations in Java web.xml files.

1) Custom Error Pages Not Configured

By default Java web applications display detailed error messages that disclose the server version and detailed stack trace information that can, in some situations, wind up displaying snippets of Java code. This information is a boon to hackers who are looking for as much information about their victims as possible. Fortunately it's very easy to configure web.xml to display custom error pages. Using the following configuration a nice error page will be displayed whenever the application responds with an HTTP 500 error. You can add additional entries for other HTTP status codes as well.

<error-page> <error-code>500</error-code> <location>/path/to/error.jsp</location> </error-page>

Additionally, web.xml needs to be configured to prevent detailed stack traces from being displayed by specifying the <exception-type> shown below. Since Throwable is the base class of all Exceptions and Errors in Java, this will ensure that stack traces aren't displayed by the server.

<error-page> <exception-type>java.lang.Throwable</exception-type> <location>/path/to/error.jsp</location> </error-page>

However, your code can still show stack traces if you do something like this:

<% try { String s = null; s.length(); } catch (Exception e) { // don't do this! e.printStackTrace(new PrintWriter(out)); } %>

Remember to use appropriate logging in addition to properly configuring your web.xml file.

2) Authentication & Authorization Bypass

The following code shows how to set up web-based access control so that everything in the "secure" directory should only be accessible to users with the "admin" role.

<security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/secure/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint>

From a common sense point of view, the <http-method> elements that specify GET and POST should indicate that *only* GET and POST requests are allowed. That is not the case, as any HTTP methods that are *not* explicitly listed are in fact allowed. Arshan Dabirsiaghi has a nice paper that summarizes this issue and shows how to use arbitrary HTTP verbs (like HEAD) and completely fake verbs (like "TEST" or "JUNK") which are not listed in the configuration to bypass web.xml authentication and authorization protections.

Fortunately, the solution is simple. Just remove all <http-method> elements from your web.xml and the configuration will be properly applied to all requests.

3) SSL Not Configured

SSL should be used to protect data in transit in all applications that use sensitive data. You can of course configure SSL on the web server but, once your app server is set up with the appropriate SSL keys, it's very easy to enable SSL at the web app level if you so choose.

<security-constraint> ... <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>

4) Not Using the Secure Flag

Many web sites use SSL for authentication but then either revert back to non-SSL for subsequent communication or have parts of the site that can still be accessed via non-SSL. This leaves the session coookie (i.e. JSESSIONID) vulnerable to session hijacking attacks. To prevent this, cookies can be created with the "Secure" flag, which ensures that the browser will never transmit the specified cookie over non-SSL.

In older versions of the Servlet specification there wasn't a standard way (although there were vendor specific ways) to define the the JSESSIONID as "Secure". Now in Servlet 3.0 the <cookie-config> element can be used to ensure that the JSESSIONID is not transmitted over plain old HTTP.

<session-config> <cookie-config> <secure>true</secure> </cookie-config> </session-config>

5) Not Using the HttpOnly Flag

Cookies can be created with the "HttpOnly" flag, which ensures that the cookie cannot be accessed via client side scripts. This helps mitigate some of the most common XSS attacks. Just like the "Secure" flag, older versions of the Servlet specification didn't provide a standard way to define the JSESSIONID as "HttpOnly". Now in Servlet 3.0 the element can be configured in web.xml as follows:

<session-config> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config>

Aside from this new standard approach in Servlet 3.0, older versions of Tomcat allowed the HttpOnly flag to be set with the vendor-specific "useHttpOnly" attribute for the <Context> in server.xml. This attribute was disabled by default in Tomcat 5.5 and 6. But now, in Tomcat 7, the "useHttpOnly" attribute is enabled by default. So, even if you configure web.xml to be <http-only>false</http-only> in Tomcat 7, your JSESSIONID will still be HttpOnly unless you change the default behaviour in server.xml as well.

6) Using URL Parameters for Session Tracking

The <tracking-mode> element in the Servlet 3.0 specification allows you to define whether the JSESSIONID should be stored in a cookie or in a URL parameter. If the session id is stored in a URL parameter it could be inadvertently saved in a number of locations including the browser history, proxy server logs, referrer logs, web logs, etc. Accidental disclosure of the session id makes the application more vulnerable to session hijacking attacks. Instead, make sure the JSESSIONID is stored in a cookie (and has the Secure flag set) using the following configuration:

<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>

7) Not Setting a Session Timeout

Users like long lived sessions because they are convenient. Hackers like long lived sessions because it gives them more time to conduct attacks like session hijacking and CSRF. Security vs usability will always be a dilemma. Once you know how long to keep your session alive you can configure the idle timeout as follows:

<session-config> <session-timeout>15</session-timeout> </session-config>

This examples has the session timing out after 15 minutes of inactivity. If the <session-timeout> element is not configured, the Servlet specification states that the container default should be used (for Tomcat this is 30 minutes). Specifying a number less than or equal to 0 means that the session will never expire. This is definitely not recommended, especially for high assurance applications.

The idle timeout can also be configured by using the setMaxInactiveInterval on the HttpSession class. Unlike the <session-timeout> element, however, this method takes the time in seconds.

In addition to the idle timeout, it would be nice if Java let you configure a hard timeout where the session would be destroyed after some set period of time even if the user was still actively using the application. Something like ASP.NET's slidingExpiration in web.config would be handy in some situations. There's no standard way to configure an absolute timeout but you could implement that logic in a ServletFilter.


Building and deploying a secure app requires input from many different stakeholders. The environment and configuration are just as important as the code itself. By thinking about some of these security misconfigurations ahead of time hopefully you can create more secure and defensible applications. Also, please comment if you have any web.xml tips of your own to share.


Frank Kim is the curriculum lead for application security at the SANS Institute and the author of DEV541 Secure Coding in Java.


Posted August 17, 2010 at 12:19 PM | Permalink | Reply


Life time filter from JSOS lets you restrict life time for sessions:

Posted September 03, 2010 at 5:32 PM | Permalink | Reply


Java is very powerful, and with such power comes the responsibility to secure it all.

Posted December 09, 2010 at 11:53 AM | Permalink | Reply

Kumar Pallav

It's a nice effort done by you to make us understand the mistakes but I want to ask about point 6 you discussed about storing JSESSIONID in URL parameter .
While I was going through jsp and servlet books I came to know We use JSESSIONID and it prevents us when cookies are disabled at client side . So , what is the point in storing even JSESSIOID even as cookies when cookies are disabled .
Will it not kill the advantage JESESSIONID gives when cookies are disabled.
I am still comparatively new to J2EE development so My question might be silly ,so pardon me for that.

Posted June 29, 2011 at 7:25 PM | Permalink | Reply


Good question, I want to know the same thing.

Posted July 19, 2011 at 12:06 AM | Permalink | Reply


I believe your app would no longer work with users that have cookies disabled. Leaving it on makes it easier for an attacker to perform session hijacking and session fixation attacks. I would choose enhanced security over catering the small number of people who don't accept cookies.

Posted January 05, 2013 at 3:17 PM | Permalink | Reply


This gives a complete new perspective to learn about different element in web.xml, hats off to you.

Posted April 15, 2013 at 3:54 PM | Permalink | Reply


I think it could be a good article, but it is a pitty that you don't come up with complete examples.
"configured in web.xml as follows
1| true"

is not quite enough for me to understand what to configure how.

Posted September 16, 2013 at 10:21 PM | Permalink | Reply


The above information is useful, in my case I must disable cookies support (a stateless system) how can I achieve this.

Posted February 18, 2014 at 3:44 AM | Permalink | Reply


Thank you very much for summarizing security features.

It's very useful information. We are planning to implement few of the security features mentioned in this article.

Post a Comment

* Indicates a required field.