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.
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.
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.
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.
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.
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:
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:
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:
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.
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.
Summary
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.
No comments :
Post a Comment