12.10.2009

Invocation is E.V.I.L., Mmkay?

This post is especially for anyone using Apache Tomcat for their application server. Today we will be discussing the EVIL InvokerServlet. What is so evil about the InvokerServlet? I mean it ships with Tomcat and has for a long time?

Let's analyze that question for a second. If you're like me, you have seen a lot of sci-fi and fantasy movies. I can think of very few examples where something being invoked was a good thing. As a matter of fact it is almost always the bad guys doing the invoking and they are almost always trying to do so to undermine and take over the world, or some other nefarious purpose in line with that.

So what does that have to do with Tomcat?

invoke (synonym: conjure)
to call forth by incantation

Let's apply this to Java:

invoke (synonym: conjure)
to call forth by FQN (Fully Qualified Name)

This is what the InvokerServlet allows you to do. By itself, in a controlled environment, it is not such a bad thing. But this is a servlet, which means, when enabled, is accesible to the entire internet, good guys and bad guys alike. All they need to do is discover the incantation, or in this case the FQN that need be uttered or passed in to make things happen.

Say for example you have a page on your site that contains a form that submits to a servlet by way of the invoker servlet. This code looks like this:

<html>
<head>
<title>This is the secret incantation page</title>
</head>
<body>
<form action="/servlet/com.yoursite.servlets.DoSomethingServlet" method="POST">
<!-- Form Elements go here -->
</form>
</body>
</html>

Any bad guy who has discovered the Right Click -> View Source option in every browsers context menu will be able to discover the secret incantation to invoke something which may be innocent enough. However, what this tells the attacker more than anything is that in your universe (website) he can learn all the secrets of your universe by trying different incantations.

Now, let's take this one step further and let's invoke the power of Google (God of the land of Search) to see what universes will easily allow us to start trying out some incantations.

Google Dork: inurl:servlet/com

Of course you can try this with net.*, org.*, or any other package descriptors you can think of. The sheer amount of results of people that are doing this and allowing this to happen are crazy.

So we still haven't really seen anything "dangerous" yet, you might be saying to yourself at this point. Well, actually you have. I have already demonstrated that you are exposing the internal structure of your source code by simply being forced to reference a class by it's FQN in a manner that is publicly accessible.

Things get even more interesting when you start tuning your query a little bit to get you more interesting results.

Google Dork: inurl:servlet/com +admin

Wow, that definately gives you some interesting stuff. Including the direct paths and information required to get admin access on a couple of sites, database usernames and passwords, and the aforementioned structure of your source code.

So let's keep going with this. Maybe using the invoker servlet, I can try to load a class that isn't a servlet at all, rather is just a POJO that lives in the classpath somewhere. To test this theory, let's try to load something that we know exists.

Url: http://hax0r-universe.org/servlet/java.lang.Object

Well, it tried to load and run the class as a servlet... Isn't that interesting. I wonder if what happens if I try to access something that I know isn't an object.

Url: http://hax0r-universe.org/servlet/java.lang.SecretIncantation

Hey, look at that, we got a 404 back from the server instead of the 500 we got when we tried to load a valid object that wasn't a Servlet.

Things are getting interesting now. I wonder if we could fingerprint and detect what libraries are running in the app server. Let's pick something that almost every application uses. Let's experiment with a Log4J class.

Url: http://hax0r-universe.org/servlet/org.apache.log4j.Logger

Hey! It tried to load it! Awesome!

I wonder if evilsite uses the version of <Insert Library Name Here> that had that really cool Buffer Overflow Vulnerability that let's me execute arbitrary code and get a shell to the server!

You see where this is going.

Using the invoker servlet opens your entire JVM to the world for discovery and probing. A dictionary powered crawl could provide a map of your entire source code tree. A vulnerable library could be exposed providing a mechanism for the bad guys to use to find that security hole in your otherwise inpenetrable fortress application. The possibilities here are endless.

So, why, after all of that, does the Apache Crew refuse to do away with the Invoker Servlet? I can't pretend to know the answer to that, but I can tell you that by default, there is no *explicit* mapping to the InvokerServlet (it is commented out in $TOMCAT_HOME/conf/web.xml) but there are a significant number of people that are uncommenting it to use it in their apps.

This is bad, mmkay. So let's stop the madness. If you are using the InvokerServlet, it is time to get over the lazyness of not adding explicit mappings to your servlets and get rid of it!

On a side note, I am investigating the possibility of including a SecureInvokerServlet (if such a thing could even be written) for inclusion in the ESAPI that provides the same kind of functionality but adds in the required Access Control, Path Whitelisting, and basic security controls that the standard InvokerServlet that ships with Tomcat lacks.

Update 1 - A good followup read is the Securing Tomcat page at OWASP

4 comments:

  1. Nice post. The invoker is commented out by default, but it was a bad insecure idea in 2001 and now it's just embarassing.

    ReplyDelete
  2. I'd still ike to know what the real implication is of being able to invoke arbitrary Java no-arg constructors.

    I'm quite happy to accept that being able to invoke arbitrary servlets is a bad idea, assuming that they can be found on the classpath, but what is so bad about invoking "new java.lang.Object()"?

    I'd love someone to be able to give a concrete example from ANY of the major libraries or frameworks where invoking any no-arg constructor leads to a security compromise.

    ReplyDelete
  3. @Rogan
    While invoking java.lang.Object is not so bad, the ability to walk your entire source tree, including any libraries that you may have in your classpath is definately a dangerous situation. An attacker could fingerprint your entire codebase, learning the structure of your code. Of greater risk is probably the ability to fingerprint the libraries that are in your classpath. For instance, say you are using an XML Library that has a known vulnerability. This vulnerability was patched by adding a new class. The attacker could identify that you are using the library by attempting to invoke an object that exists in the vulnerable library, then try to invoke a class that exists in the patched version. If he recieves an error screen telling him that the second object doesn't exist, he knows that you are using the vulnerable version of the library and has a target to try and exploit. Disclosing source code information in general can seem relatively harmless at first, but this is a huge gaping hole that, if it hasn't been exploited yet, will be eventually.

    ReplyDelete
  4. Also - this could present a potential DoS situation if you have a large set of libraries and a large codebase and limited memory on your server. I have seen codebases with 100+ libraries when in fact only a select bit of them were actually being used. If you force the classloader to load *every* class from *every* library available in the classpath, this could pretty easily eat up memory and cause the GC to fall behind. Imagine if I fired off a few million requests for java.lang.Object from a botnet repeatedly. I would have to try it to prove the theory, but it is a very real possibility.

    ReplyDelete