Sunday, December 2, 2007

Hardening Utils Part 1: HDIV

Security can be implemented into a J2EE application on both programmatic as well as declarative ways. The much more flexible one is doubtless the later one which can be archived by using servlet filters or listeners and few lines in the specific deployment descriptor (web.xml). Some interesting projects have recently been kicked-off addressing certain security features in such a declarative fashion. I call them J2EE hardening utilities. The first, and probable most powerful one, I want to talk about is HDIV. Before I can do this, however, I have to explain one of its most interesting features: page tokens.

Page Tokens

As I have already explained in my last writing, HTTP is stateless so we need a session id (JSESSIONID) send either by cookie or within the url in each session-related request. By including such an id, a user can usually access all resources, no matter whether he has been given a specific link to it or not. This fact allows attacks such as Cross-site Request Forgery (CSRF) to be carried out. An attacker can send a link like http://application/?action=delete to an user authenticated to execute a certain command within the user's session and without ones noticing it. Of course this kind of attack would only be possible when the victim uses cookies for transmitting his session, because otherwise the URL wouldn't be generic any more and not foreseeable by the attacker, respectively. What we have to do here to prevent this attack is to include some session-related token into the URL in addition to the session cookie. This technique is known as session tokens.

We can improve this by using tokens which are not only related to the session but also to a certain page the user has received. This token can then be evaluated to only allow the user to access those pages he has provided a link to from the application itself. With this technique we can not only harden our applications session management but also the whole authorization system since the user can't access restricted pages such as http://application/admin when he never has provided a link to it.

The HDIV State

The HDIV state is basically an implementation of the page-token idea I talked above. Well, it can actually do even more then that. It distinguishes between two sets of HTTP parameters: those which are editable by the user such as input fields, text fields and so on and those which should normally never been manipulated by the user such as hidden fields. The later (non-editable parameters) are automatically included within the HDIV state object and validated on discrepancies on each client request. For being able to provide this feature in a transparent and automatic fashion, HDIV facilitates two techniques: First, it implements a servlet filter to check the correctness of the parameters provided.
Second, it extends various taglib libraries (Struts, Spring MVC and JSTL) to automatically insert the HDIV state as an additional parameter in all kind of link elements such as or as an extra form element (hidden field). This depends on how you configure HDIV, this state parameter can then either be a short reference to the state object in the users session object (example: _HDIV_STATE_=12-23-2323) or a pretty nasty long parameter holding all state data in a encrypted and base 64 encoded way, respectively. Since certain sites such as start pages (/index.jsp) should or must be accassable without any state information, these pages can of course easily be excepted of HDIV's validation. As complicated it might sound at first, HDIV is a pretty easy to handle tool and provides your application an awesome amount of security out of the box, as long as it fully facilitates one of the supported frameworks (Struts, Spring MVC or JSTL).

Here is an example source code snippet from an HDIV secured site:







The HDIV Validator

HDIV comes with a nice validator functionality allowing you to check all ingoing parameter values for suspicious characters (such as
<>," ) that could be facilitate by an attacker to carry out an Cross-site Scripting attack, SQL injection and so forth. Since HDIV only allows editable parameters to be manipulated by the user, validation rules have only to be applied to those parameters (e.g. input fields). However, since HDIV is based on Spring its configuration is pretty long-winded for implementing an own validation rule base. In one of my next postings, I will present a much more suitable tool for this job: OWASP Stinger.

More Features

HDIV also supplied several additional features I haven't talk about yet. One example is Cookie protection, which works roughly in the same way as with non-editable parameters. The other is parameter obfuscation, where all parameter names and non-editable parameter values, are obfuscated by HDIV so that an attacker can get no clue about the function of this as he might would get when seeing parameters such as "id" (database object id) or "file=/test.jsp" (possible filename injection). Instead he will only see a query string like "1=1&2=2" which HDIV will map transparently to its real values stored in the state object before they are send to the application. HDIV has even more that it can do, just have a look at its decent documentation.

Sunday, November 11, 2007

Cookies vs. URL Rewriting

When it comes to session management, developers most likely think firstly of cookies and secondly of the servlet container which normaly takes care of this.

The problem with the former is that cookies are actually just one of two common J2EE session tracking mechanisms. According to the Servlet 2.4 specification, “when a client will not accept a cookie, URL rewriting may be used by the server as the basis for session tracking“. J2EE servers like Tomcat, WebLogic and most others follow this rule by default.

The problem with the later is that most J2EE servers do in fact a good job when providing session management functionality to their hosted applications from performance and reliability point of view. Security, however, is not one of these. In fact, security aspects of the session management are not even mentioned in the servlet spec at all, which makes it to a proprietary issue of the application server and to the web application, respectively. Each session tracking mechanism has its own group of weaknesses. All of them have to be considered, when both mechanisms are supported.

But what are this session related threats. Well first of all, the randomness of the id is not one of them. From what we now, the sessionid algorithms are pretty good implemented by all J2EE , guaranteeing a cryptographic random value, which will not be guessable by an attacker, especially not over the Internet.

The risks are different are specific to the tracking mechanism itself. Let’s start with cookies.

COOKIES

As I mentioned above, cookies are the default tracking mechanism according to the spec. A cookie will be set by the server in a HTTP response header like

Set-Cookie: JSESSIONID=123; Path=/MyApp; secure

and automatically inserted into the HTTP header of all requests (JSPs, images, html, you name it) as long as the restrictions from the Set-Cookie statement do apply.

These restrictions are:

  • validity (default: end of browser session)
  • scope (default: the whole host)
  • protocol (default http and https)

The server does not now why it received a particular cookie from the client, tough, because the applied restrictions are not part of the corresponding cookie statement of the HTTP request. All what the server gets from the client is a name and a value of this cookie:

Cookie: JSESSIONID=123

This does, however, only apply to cookies according to RFC2109 (also known as V0 cookies), which the standard today, though. Cookies according to RFC2965, also known as V1 cookies, corrected this issue and will hopefully be the standart one day.

Why is this behaviour now so important? The problem of the way of how (v0) cookies are implemented is that this is an tracking mechanism which is controlled by the browser. When a browser requests a URL it has a valid cookie in his (cookie) jar for, it automatically attach this cookie to the request without the user’s knowledge. This is not only a potential privacy risk for the user; it is also a security risk for the web application.

By default, a cookie will be send to all applications on the same host. If there is one single insecure application with an XSS vulnerability, an attacker can disclose the session id and compromise all applications on the same host through it.

The other major risk of session tracking by cookies is Cross-site request forgery (CSRF), where an attacker silently executes an action on the behalf of an authenticated user by just sending a crafted URL to him. When the user clicks on this link and his browser will automatically sends the cookie with the request and the application will execute it, because it simply has no chance to figure wheter this request was deliberately send by the user or not.

URL Rewriting

URL rewriting is the technique of transporting the Session ID within a Unified Ressource Locater better known as URL. Clients without cookie functionality such as many mobile devices still depend on URL rewriting. In older J2EE servers, such as WebLogic 6 and earlier, this was once done within a query parameter. As of Servlet 2.3 specification this behaviour is implemented as a path parameter in the URL string like this:

http://[host]/edit.jsp;jsessionid=123?param=1

The sessionid is placed here by the application. Within a servlet this is done with encodeURL() and encodeRedirectURL(), respectively.

But how can an application unintentionally support URL rewriting, when it does not consider it in any way. Well, this is quit easy. Most taglibs like the JSTL or Struts automatically support URL rewriting. Unlike to an HTTP header which transports cookies, a session IDs in a URL can be disclosed on many ways, for example:

  • log files
  • the browser history
  • by copy-and-pasting it into an e-mail or posting
  • the HTTP Referrer

If the session id is not renewed after the login, URL rewriting can also be used for another attack: Session Fixation. Here, an attacker goes to the site and grabs a URL, such as http://mysite/login;jsessionid=123 and sends it in some way (such as an email) to his victim. After the victim logged in, the attacker will have full access to the victims session.

The good thing of URL rewriting, however, is that session tracking is now controled by the server and application, respectively.

Which to Choose

Generally, it’s not a bad idea to only support one tracking mechanism, so you just have to deal with the threats of one of them. But which is the best to chose? Unfortunately, there is no absolute answer to this question. One group of experts say URL rewriting is better the other say cookies are. In fact, it really depends on how you rate the specific threats I talked about before.

Disabling cookies can easily be done with a WebLogic, WebSphere as well as a Tomcat server. In the case of Tomcat, for instance, you just have to add "cookies=no" to the application’s context declaration at server.xml.

Forcing cookies gets a lot trickier. At least when you use a Tomcat server, because there is no simpar option like "urlrewriting=no". And even if you use a WebSphere or WebLogic server which allows you to disable URL rewriting, you might want to react on a browser having with cookies disabled, which an appropriate error page.

This can be implemented with and simple sevlet filter like this:

public class CookieEnforcer implements Filter {
private String errorPage;

public void init(FilterConfig FilterConfig)
throws ServletException
{
if (FilterConfig != null) {
errorPage = FilterConfig.getInitParameter("error_page");
}
}
public void doFilter(ServletRequest req,
ServletResponse rsp,
FilterChain chain)
throws ServletException, IOException
{
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpSession session = httpReq .getSession(false);

if ( (session != null) &&
(httpRequest.isRequestedSessionIdFromURL() ))
{
request.getRequestDispatcher(errorPage).forward(req,rsp);
}
else {
chain.doFilter(req,rsp);
}
}
public void destroy() {}
}

The corresponding declaration in the web.xml file has to look like this:

<filter>
<filter-name>CookieEnforcer</filter-name>
<filter-class>examples.CookieEnforcer </filter-class>

<init-param>
<param-name>error_page</param-name>
<param-value>error.jsp</param-value>
</init-param>
</filter>

The Silver Bullet

The silver bullet here is to establish a two factor session management which combines a factor from the URL with one of the header in some way. This can be most easily be done by utilizing cookies together with a page or session specific token in the URL.

In one of my next postings, I will describe more detailed on how to practically implement this approach under J2EE, for example with HDIV.

Thursday, November 1, 2007

Why This Blog ?

Developing modern enterprise web applications has become an increasingly complex process. Developers have therefore to continuously embrace new technologies and frameworks to be able to keep up with this trend. But new technologies are also new possible ways an attacker might exploit.

The OWASP, for example, lists no less than 500 common web application vulnerabilities on its website. From a security professionals perspective, most of these threats are well understood and documented. But when it comes to implementing adequate countermeasures in a J2EE application, the available information is mostly authentication and authorization. The most vulnerabilities, however, do not relate to these both topics at all, but to session management and, even more, to data validation instead.

This is why I had the idea to start this blog to discuss common vulnerabilities and counter measures, but also technologies and ideas for securing J2EE/Java EE web applications. I hope you will find this blog interesting and useful for your daily work.

To My Person

I started as a software developer nearly nine years ago. At first I was writing web applications with PHP and later with ASP.NET and J2EE. I now work as a security consultant. Most of the time I am busy conducting security assessments (pentests), trainings and working on a couple of J2EE projects.