Beware the HTTP path parameter

No Gravatar

Please forgive the title, but today’s topic is something to be wary of if you write (or use) any access control / authorization type code in web-based j2ee apps: HTTP URL path parameters. Many people are unfamiliar with them (as they are uncommon), but they are something you should be aware of. A nice simple description of url path parameters can be found here. Essentially path parameters are the bit of a url path that comes after a semi-colon (semi-colon is the most popular path parameter delimeter). So, here’s an example of 2 urls, each with an http path parameter:

http://www.mysite.com/admin/UpdateUserServlet;jsessionid=OI24B9ASD7BSSD
http://www.mysite.com/admin/UpdateUserServlet;/user/HomeServlet

We’ve all seen the first example probably many times where a jsessionid gets attached to our url. However, take a look at the second example. Pay very close attention to what is being presented here. This represents a request that is going to go to the administrative UpdateUserServlet, but with a path parameter of /user/HomeServlet. Now, what could be the problem here? Well, there actually turns out to be 2 different issues to deal with in most cases.

Issue 1 – The server product and version

The first issue to contend with is how your servlet container/app server product and version handles certain request APIs, as apparently different products and even versions deal with http path parameters in different ways. (I have not done the work to determine which servers and versions are affected, but you should do that in your own environment, as apparently even configuration changes can cause slightly differing behavior. These variations are caused by – read blamed on – a lack of clarity in the servlet spec regarding path parameters.)

This problem can be seen when using certain API calls from the HttpServletRequest object and seeing how those APIs handle path parameters. Two of the affected methods are getContextPath() and getServletPath(), where there are variations between whether or not these calls actually strip out any path parameters depending on server and version. Again, this testing is left as an exercise to the reader. We’ll see below what can happen when we make poor assumptions here.

Issue 2 – Your code

Here is where the actual problem really shows up … when we actually use these APIs. One of the most common uses is for writing access control / authorization code. Many access control frameworks or internal codebases use a url mapping concept of some kind. They vary widely in how they are implemented, but a simple example might be: anything with “/admin/” in the path requires the admin role, or anything that ends in “UpdateServlet” requires the manager role. Let’s use the “ends with” example and walk through some code.

String uri = request.getRequestURI();	//note getRequestURI will always return the full path with path parameters but not request parameters
if (uri.endsWith("UpdateServlet")) {
    //require the manager role here
} else {
    //just require standard user role
}

This is a very trivial piece of code, but will be similar in spirit to what is in lots of access control code in j2ee apps. Here the developer was expecting the user to send a request that looked like

http://www.mysite.com/app/UserUpdateServlet

when they were trying to get to the update servlet. But what happens if the user sends a request like

http://www.mysite.com/app/UserUpdateServlet;/app/UserReadServlet

HERE’S THE PROBLEM! Now the app code has checked the URI, and sees that it ends with ReadServlet and not UpdateServlet, so it only requires the standard user role, and the access control check passes. But the app server/container sees that the ACTUAL request is going to UserUpdateServlet, and allows the user to go there. Now we have a access control bypass issue! The user has been able to circumvent your “protection”.

DOH! Ok, now what …?

Fixing the problem

There are several ways you could address this issue, and each option varies in difficulty and correctness.
1. You could whitelist all of your allowed requests and compare them to pre-determined acceptable urls, but that might get cumbersome with a very large app.
2. You can perform some cleansing (stripping) of the url path parameters, but that can be an issue if your app server allows various path parameter delimeters.
3. You can also compare from the start of the URI or path instead of checking the end. This might be similar to the whitelist option
4. Another option that should definitely be used is to check your app server/container (on every upgrade as well) to see what it’s actual behavior is regarding path parameters).
5. Another option might be to perform your access control check at the beginning of a request handling piece of code, like a servlet, or action. That way, you know that’s the code actually being executed, so it’s the url you should be verifying. This has the problem of a lack of centralized control however.

There are certainly more options here, and you know what will work in your code, but hopefully the options above help as a starting point. Hopefully you found this information helpful and are able to update your projects to fix the issue if it exists.

References

Much of my research for this article came from an important bug in the Spring Security (formerly Acegi) project that was caused by this path parameter issue (bug found by Ed Schaller). More information can be found at the following 2 urls.
http://www.springsource.com/security/cve-2010-3700
http://seclists.org/fulldisclosure/2010/Oct/437

Special Author Note

This topic was first shared with me by Abraham Kang. He both introduced me to this issue and reviewed this article for me. Thanks Abraham!

Be Sociable, Share!

Technorati Tags: , , ,

2 thoughts on “Beware the HTTP path parameter

Leave a Reply

Your email address will not be published. Required fields are marked *