Support: @fraud_world &

Tutorial Oracle SQL Injection - Complete


New member
0x00 Introduction

The article deals with the peculiarities of SQL-injection vulnerability in the code DBMS Oracle. Although now rarely seen in the DBMSs using this web programming, but still it happens.
Article amended since the last publication.

0x01 Features

First, give some properties that must be considered during the injection in Oracle. Just want to mention that in the article the injection in the statement SELECT. While an injection in INSERT, UPDATE, and DELETE, it is also possible.
It is also important also the fact that the article deals with the injection is in a query SQL Oracle, but not in the procedures of PL/SQL Oracle. The significant difference in the injection procedure PL/SQL is the ability to use query separator - a semicolon ';'. But IMHO it is about to write a separate article that describes all of the consequences. Especially since the author believes that Web applications are most common injection site is in a query SQL (at least I came across just such).
In Oracle, as well as in MySQL and PostgreSQL, an injection is carried out by using a UNION, ie with the preparation of the union of two queries (hereinafter referred to for ease of understanding, the term - a subquery). But in addition to matching the number of columns in the main query and the subquery must be borne in mind that Oracle does not automatically cast in a subquery. Therefore, the selection of columns to substitute the null, unlike, for example from MySQL.
It is also very important property is that all the SELECT queries should be made of a table, ie query syntax must always contain the word FROM and the table name. For simple arithmetic or other operations that do not require a real table in Oracle there is a pseudo-table SYS.DUAL.
An important feature is the absence of operator LIMIT.
To truncate a query using comment characters "-" (two dashes), and "/ *" (forward slash and asterisk) in SQL Oracle. The first type, single-line comments. The second type - multi-line.
There is the possibility of using SQL Oracle multiple requests using the delimiter ";", in contrast to the procedures in PL/SQL.
If an error is detected can be uniquely identified Oracle, by the presence of the words in the text ORA error messages such as:

[Macromedia][Oracle JDBC Driver][Oracle]ORA-00933: SQL command not properly ended

Not always in the error message with the word Oracle, for example:

Warning: OCIStmtExecute: ORA-01722: invalid number in

0x02 Selection of columns

Suppose there is an error in the parameter id:


Determination of the number of columns present in the main query is the same as in MySQL. Since the UNION operator requires the same number of columns in the main query and the subquery we need to determine the number of columns. With incorrect identification of the columns in the subquery output standard error message:

ORA-XXXXX: query block has incorrect number of result columns

For selection of the column there are 2 known ways:

A. A simple case.

Construct the following query


If the error occurred, increasing the number of columns in a

Code:, null+from+sys.dual--

and so until there is no error.

Two. Using the ORDER BY clause

The second method is much faster and more pleasant, if a sufficiently large number of columns.

Construct the following query


If there is no error, then one or more columns of a


If such a request must receive an error, which means the column is less than 99999. Further, in the same way restrict the boundaries of the selected interval on the left and right, and ultimately determine the actual number of columns in the main query.

0x03 Determination of output columns

For example, we have determined the exact number of columns in the main query, let them 4.

Code:, null, null, null+from+sys.dual--

Now we need to define the columns that are displayed on the page. Usually involved in the withdrawal of the columns with data types int, char and data. We will be sufficient printabilnyh columns with types int and char, and they'll look for it.

As noted earlier, Oracle does not automatically cast in a subquery. Therefore, when trying to insert into any column is the wrong type, we get the following error type mismatch

ORA-XXXXX: expression must have same datatype as corresponding expression

Then we begin to make inquiries, in turn, replacing each column to any number of

Code:, null, null, null+from+sys.dual--


Code:, 123, null, null+from+sys.dual--

Thus, we will identify printabelnye columns with type int. In the event that we get a type mismatch error, we can use the type conversion functions to_char(), to_date() and identify the types of columns printabelnye char and data.

Code:, to_char(123), null, null+from+sys.dual--

For reference, the syntax of the function to_char():

to_char( value, [ format_mask ], [ nls_language ] )

Getting the information.

Once we know the number of columns and which ones printabelny, we can safely go to obtain necessary information from the database. Well, if we know the specific tables and columns in the database they then receive the information will not be difficult. For example, if there is a table with columns USERS ID, LOGIN and PASSWORD, then the request for these data is as follows

Code:, login, password, null+from+users+where+id=123--

Just as in MySQL, for the convenience of maps and overcome various problems with the encoding you can use the function concat(), to_char().

To overcome the filtering quotes or other essential characters, there is a function chr().

0x04 Bypass filtration

Bypass filtration quotes and other special characters by using the chr().

The function chr() returns an ASCII-character code. But its use is associated with some difficulty, because the function accepts and returns only one character in contrast to the similar function char() in MySQL. To obtain the entire line will have to call a separate function for each character, and later combine them with the concatenation ||.

Thus, the encoded word user will have the form chr(117)||chr(115)||chr(101)||chr(114).

0x05 Tables and columns

If the user tables are unknown to us, then we can get various information from system tables known Oracle.

Learn the name of the user that runs the interface, and therefore you can be calling the user or sys.login_user

Code:, user, null, null+from+sys.dual--

Get a list of sessions can be like this: select * from V$session

Of great interest are the table and SYS.USER_TABLES SYS.USER_TAB_COLUMNS, which contain all the tables and their columns are available to the user. We take out the table and column names:

Code:, table_name, null, null+from+sys.user_tables--

Code:, column_name, null, null+from+sys.user_tab_columns--

Also, in my opinion, in addition to the table SYS.USER_TABLES table_name, are of interest following columns: tablespace_name, num_rows, freelist_groups.

Thus, we can look at all the names of the tables turn. The same storage structure, we can use to view the table SYS.USER_TAB_COLUMNS, upon receipt of all the column names available to the user.

Also, there is a concept in Oracle prefix of the object (the table is an object) that is present in the title or name of the table:

ALL_ - all available to the user (the owner might not be)

USER_ - objects whose owner the user is.

Therefore, we can simplify your task and get the names of only those tables for which we have access

Code:, table_name, null, null+from+sys.all_tables

Interest can also provide information for the following standard tables: SYS.USER_OBJECTS, SYS.USER_VIEWS, SYS.USER_VIEWS, SYS.USER_CATALOG, SYS.USER_TRIGGERS, SYS.TAB.

0x05 Analogues LIMIT

But, unfortunately, made the above requests will lead us to only one - the first record of the entire table. There is an irresistible desire to take advantage of the operator LIMIT, like in MySQL or PostgreSQL. Much to everyone's dismay, this operator is not supported in Oracle, and moreover has no decent equivalent in the form of another operator.

"All is lost!" - You might say.

"NO!" - I will answer you.

Suffer badly google, I finally found an opportunity to make a complex query somehow vaguely realizes the meaning of the operator LIMIT. Unfortunately, not able to restore its capacity in full.

Code:, table_name, null, null+from+sys.user_tables+where+rownum+<=+5--

Thus, consistently turning over records in the sample, we obtain an analogue of LIMIT.

However, it is not as efficient as the proposed method further.

Possible replacement of the normal predicate used LIMIT in MySQL to Oracle using the pseudo-ROWNUM using a complex query (thank groundhog `y).

Use the following construction:


Looking over the X and Y take out the names of all tables (all entries from X to Y), available to the user, similar to columns.

A few interesting designs with ROWNUM:

Bust of table names in a given NUMROW (returns one line)


Get the number of entries in the table given by NUMROW


Get the number of entries in this table by table name


0x06 Passwords

If we are lucky and the user, under which we work with the database, has the right sysdba, then we can get the hashes of all users of the base.

Main place of storage of the password hash (hash) - table of the dictionary SYS.USER $. Above this table was built as a basic derivative, SYS.DBA_USERS. If the user profile is enabled PASSWORD_REUSE_TIME, password hash is also stored in SYS.USER_HISTORY $. Get the hashes and user names can be like that:

Code:, username, password, null+from+sys.dba_users
For completeness also present an algorithm for computing the convolution password, just in case someone might come in handy:

0x07 Google dork

Like right now customary to use search engines to find vulnerabilities, we also will not keep up (=
In order to identify vulnerable sites can use a search engine such as google to search for sites with strings
"ORA-00921: unexpected end of SQL command"

0x08 Copyrights

This article used the following materials:
How to crack password protected Oracle or her around, Article VI Przyjalkowski,
And also used the documentation for Oracle 10i.
Top Bottom