Oracle RCE & more
RCE: Java Store Procedure
So, imagine that you have the administrator account information. In this case, a very popular way to execute your command on the server is to write a ‘java stored’ procedure. This is done in three stages. First, create a Java class called ‘oraexec’. To do this, connect via ‘sqlplus’ terminal and write:
Next, write a PL/SQL wrapper for this class:
That’s it. Now, to execute a command, all you need is just to send the following query:
Note that when using the above procedure, we cannot see the results of executed command, however, you can redirect the output to a file and read it. You can find the full code of the shell that allows to read and write files:
However, there is a [more sophisticated script] (goo.gl/EuwPRU) that handles the command output, but it has a larger size here.
RCE: Scheduler
The next method, which will help us if there is no Java virtual machine, is to use ‘dbmsscheduler’, the built-in task scheduler of Oracle. To use it, you must have the privilege ‘CREATE EXTERNAL JOB’. Here’s a code sample that implements the entry of ‘0wned’ string into a text file in the root of the C: drive:
This will create and run a job for executing your command. And here’s an option for calling the Scheduler from another procedure – ‘SYS.KUPP$PROC.CREATE_MASTER_PROCESS’, which is of interest to us, primarily, because it allows you to embed multi-statement queries, that is, those consisting of multiple sub-queries. Theoretically, you can run such query even in case of injection into a web application.
Note that, when you use the Scheduler, you can run this job more than once and do it with some frequency. As a result, this will help you get a foothold in the tested system, because, even if the administrator deletes the user from OS, this job, which is regularly running in the system, will bring him or her back to life.
RCE: External Tables
As the last method for achieving the execution of OS commands, I would like to mention the use of External Tables. This method will help you later download files from the server. You will need the following privileges:
UTL_FILE;
CREATE TABLE;
a directory reserved for the user.
Let’s remember that the access to ‘UTL_FILE’ package is by default provided to all accounts with ‘CONNECT’ role. Step one: Check the issued directories with the following query:
Step two: Create an executable batch file with desired command:
Step three: Prepare the external table ‘EXTT’, you will need it to run the file:
Now, just call your batch file with the following command:
The terminal will start to display error messages that the system cannot match the table and invoked file but, in this case, it is not important, as the main objective was to open the executable file, which you have achieved.
‘ODAT.py’ utility also can implement this attack. However, it requires the privilege ‘CREATE ANY DIRECTORY’, which, by default, is granted only to DBA role, since it attempts to execute the file from any and not only “your” directory.
Read/Write files
Now, let’s proceed to the task of reading and writing the files. If you simply need to read or write a file to the server, you can do it without any Java procedures, which, however, can also handle such tasks. Let’s have a look into ‘UTL_FILE’ package that has the functionality required for working with the file system. The good news is that, by default, it can be accessed by all users with ‘PUBLIC’ role. The bad news is that, by default, this procedure has no access to the entire file system, but only to a directory pre-defined by the administrator. However, it is not uncommon to find a directory parameter specified as ‘*’, which literally means “access to everything.” You can find this out by using the following command:
I found that the shortest procedure for using ‘UTL_FILE’ package is proposed by Alexander Polyakov:
If you need more functionality with the ability to write, I recommend to google a script called ‘raptor_oraexec.sql’. And according to tradition, here’s an option for using ‘ODAT’ utility, which, as always, is the shortest:
‘UTL_FILE’ package is also very interesting because if you’re lucky, you can reach the logs, configuration files and obtain passwords from privileged accounts, such as ‘SYS’.
The second method that I would like to mention is to use again the ‘External Tables’. Remember that, when using ‘External Tables’, the database can access in read mode the data from external tables. For a hacker, this means yet another opportunity to download files from the server, but this method requires ‘CREATE ANY DIRECTORY’ privilege. I suggest immediately using ‘ODAT’, as it is stable and fast:
Elevating Privileges
You can use various methods to elevate privileges, ranging from classic buffer overflows and DLL patching to specialized attacks against databases, such as PL/SQL injections. The topic is very extensive and, in this article, I will not dwell on it, as this is discussed in large research papers, such as those found in the blogs of [Lichfield] (goo.gl/IebQN4) and [Finnigan] (goo.gl/vXhttf). I will just demonstrate some of them, so that you have a general idea. During the testing, I recommend simply paying attention to current privileges and, based on this, search for desired loopholes in the Internet.
Unlike MS SQL, where an attacker can inject ‘xp_cmdshell’ almost immediately after ‘SELECT’ by simply closing it with a quotation mark, Oracle DB flatly rejects such tricks. For this reason, we cannot every time resort to classical SQL injections although, in this case, too, it is possible to find a way out. We will consider PL/SQL injections, which are modifying the process of executing a procedure (function, trigger, and other objects) by embedding random commands into available input parameters. (с) Sh2kerr
In order to embed the payload, find a function where the input parameters are not filtered. Remember that Oracle SQL does not allow multi-statement (multiple) queries, therefore, most likely, you will need to use some “special” procedures that have this feature. The main idea behind the attack is as follows: By default, unless specified otherwise, the procedure is executed on behalf of the owner and not on behalf of the user who started it. In other words, if a procedure owned by ‘SYS’ account is available for execution and you can embed your code into it, your payload will also be executed in the context of ‘SYS’ account. As I already mentioned, this is not what happens always, as there are procedures with ‘authid current_user’ parameter, which means that this procedure will be executed with privileges of the current user. However, usually in each version, you can find some functions that are vulnerable to PL/ SQL injection. A general view of this process is shown in Fig. 2.
In short, instead of expected legitimate argument, we pass some malicious code that becomes a part of procedure. A good example is provided by ‘CTXSYS.DRILOAD’ function. It is executed on behalf of ‘CTXSYS’ and does not filter the input parameter, which allows you to easily rise up to DBA:
However, by now, this is probably history, since the vulnerability was found in 2004, and it affects only the old versions 8–9. Usually, the process of escalating the privileges is divided into two parts: writing the procedure that increases the rights and performing the injection itself. A typical procedure is as follows:
Now we can inject a procedure as an argument of vulnerable function (example for versions 10x):
In the not too recent versions 10 and 11, there is one “nice” exception, or rather a vulnerability, that allows you to execute commands on the server without having DBA rights: ‘DBMS_JVM_EXP_PERMS’ procedure allows a user with ‘CREATE SESSION’ privilege to get ‘JAVA IO’ rights. The attack can be mounted as follows:
Now that you have the privileges to call up Java procedures, you can evoke a response from the Windows interpreter and execute something:
Last updated