2004
Smitha Padmanabhan
[SQL INJECTION] An overview of SQL Injection in Oracle based applications and prevention techniques
Newsletter: SQL Injection
Page 2
Table of Contents
SQL INJECTION IN ORACLE BASED APPLICATIONS ..........................................................3
What is SQL Injection?................................................................................................... 3
Purpose of SQL Injection................................................................................................ 3 How Can Oracle be abused? ........................................................................................... 4
How does an Oracle Based Internet Application work? ................................................. 5 Some Specific Examples................................................................................................. 5 PL/SQL Packages, Procedures and Functions ................................................................ 6
Enumerating the Privileges ............................................................................................. 7 Error messages leaking information ........................................................................... 7
Finding accessible objects........................................................................................... 8 Get the Roles ............................................................................................................... 8 System Privileges ........................................................................................................ 9
Prevention of SQL Injection ......................................................................................... 10 Detecting SQL Injection ............................................................................................... 11
Least Privilege............................................................................................................... 11 References:.................................................................................................................... 12
Newsletter: SQL Injection
Page 3
SQL INJECTION IN ORACLE BASED APPLICATIONS
The intention of this newsletter is to discuss SQL Injection Vulnerability in Oracle based
applications. It covers the various ways in which SQL can be injected to Web Applications with
practical examples. This newsletter discusses some of the coding standards, development
practices, data validation and database lock down issues related to this. It briefly covers what
DBAs can do to possibly “detect” SQL Injection attacks.
What is SQL Injection?
SQL Injection is a way to attack the data in a database through a firewall protecting it. It
attacks on the web application itself rather than on the web server or services running in the
OS. It is a method by which the parameters of a Web-based application are modified in order
to change the SQL statements that are passed to a database to return or manipulate data.
SQL Injection occurs when an attacker is able to insert a series of SQL statements into an SQL
statement by manipulating data input to an application. For example, by adding a single quote
(‘) to the parameters, it is possible to cause a second query to be executed with the first.
What does an attacker need? Any web browser.
Purpose of SQL Injection
An attack against a database using SQL Injection could be motivated by two primary
objectives:
1. To steal data from a database from which the data should not normally be available,
or to obtain system configuration data that would allow an attack profile to be built.
One example of the latter would be obtaining all of the database password hashes so
that passwords can be brute-forced.
2. To gain access to an organization’s host computers via the machine hosting the
database. This can be done using package procedures and 3GL language extensions
that allow O/S access.
There are many ways to use this technique on an Oracle system. This depends upon the
language used or the API. The following are some languages, APIs and tools that can access
an Oracle database and be part of a Web-based application.
JSP
ASP
XML, XSL and XSQL
JavaScript
VB, MFC, and other ODBC-based tools and APIs
Portal, the older WebDB, and other Oracle Web-based applications and API’s
Reports, discoverer, Oracle Applications
Newsletter: SQL Injection
Page 4
3- and 4GL-based languages such as C, OCI, Pro*C, and COBOL
Perl and CGI scripts that access Oracle databases
Many more.
Any of the above applications, tools, and products could be used as a base from which to SQL
inject an Oracle database. A few simple preconditions need to be in place first though. First
and foremost amongst these is that dynamic SQL must be used in the application, too l, or
product, otherwise SQL Injection is not possible.
SQL injection is not just a Web-based problem. As is implied in the preceding paragraph, any
application that allows a user to enter data that may eventually end up being executed as a
piece of dynamic SQL can potentially be SQL injected. Of course, Web-based applications
present the greatest risk, as anyone with a browser and an Internet connection can potentially
access data they should not.
Data held in Oracle databases should be protected from employees (Internal Users) and others
who have network access to applications that maintain that data. Those employees could be
malicious or may simply want to read data they are not authorized to read. Most threats to
data held within databases come from authorized users.
Protecting against SQL Injection on Oracle-based systems is simple in principle and includes
two basic stages. These are:
1. Audit the application code and change or remove the problems that allow injection to
take place.
2. Enforce the principle of least privilege at the database level so that even if someone is
able to SQL inject an application to steal data, they cannot see anymore data than the
designer intended through any normal application interface.
How Can Oracle be abused?
Oracle is like any other database product and, as a result, is vulnerable to SQL injection
attacks. While Oracle fares slightly better than some of the others, the following abuses can be
inflicted on an Oracle database:
UNIONS can be added to an existing statement to execute a second statement
SUBSELECTS can be added to existing statements
Existing SQL can be short-circuited to bring back all data. This technique is often used
to gain access via third party-implemented authentication schemes.
A large selection of installed packages and procedures are available, these include
packages to read and write O/S files;
Data Definition Language (DDL) can be injected if DDL is used in a dynamic SQL
string;
INSERTS, UPDATES and DELETES can also be injected; and,
Other databases can be injected through the first by using database links.
Newsletter: SQL Injection
Page 5
On the other hand, the following abuses are not possible:
Multiple statements are not allowed; and,
It is also not possible to SQL inject a call that uses bind variables; this is therefore a
good solution to most of the SQL injection issues.
How does a Web PL/SQL Application work?
The main components of an Oracle based Internet application are an Oracle database and an
Oracle application server that communicates with the database. A Database Application
Descriptor (DAD) needs to be set up on the application server. The DAD is a set of information
that tells the Application Server about database connection specifics such as database
username, password, connect string (TNS service name), and log file. The application server
will have an open connection to the Oracle database through the DAD using the db username
specified in the DAD. So all internet users communicate to the database using the db
username specified in the DAD.
Some Specific Examples
The below example illustrates some of the possibilities of SQL injection on Oracle. As stated in
the introduction, it is possible to inject into any piece of SQL that is dynamically built at run
time where the input data is not filtered or checked.
These procedures use native dynamic SQL to pass a run-time piece of SQL to the database.
Case 1:
Type in Jones in the Last Name field. It correctly pulls up the phone number 999555888.
The application uses dynamic query to pull this info. The query string is below:
'select customer_phone' || ' from customers ' ||
'where customer_surname=''' || pv_surname
|| '''';
Case 2:
Now copy and paste the following string to the Last Name field on the form
x' union select username from all_users where '1'='1
This displays the Database User Names instead of the phone numbers !!
Sub queries could be used to extend an existing select statement. These are less useful, as
they cannot alter the existing select list used to add new columns from other tables; however,
they can be used to alter which records are returned by the existing query. An example is
shown to return all of the records in the table:
Newsletter: SQL Injection
Page 6
x' or exists (select 1 from sys.dual) and 'x'='x
You don’t need to know anything about the database table.
There are other SQL Injection Techniques where the rest of a where clause is truncated so
that all of the records in the table are returned. The classic use of this is the case where
method of logging in is to find a valid record in the users table where the username and
password match. Such an example could be:
select * from my_user_table where username=’someuser’ and
password=’somecleverpassword’
We can make the SQL return all of the records in the table; this usually allows a login to occur.
All of the records can be returned by using an “OR ‘x’=’x’” in the where clause as follows:
select * from my_user_table where username=’’ OR ‘x’=’x’ and
password=’somecleverpassword’
(OR)
select * from my_user_table where username=’ someuser’ and password=’’ OR
‘x’=’x’
In the above examples we have seen select statements being injected with extra SQL. The
same principles also apply to insert statements, update statements and delete
statements. Other statements available in Oracle include DDL (Data Definition Language)
statements, which are statements to alter the schema or database instance. Examples include
creating tables or indexes or altering the language set used. Statements cannot generally be
mixed because, we cannot just send two statements to the RDBMS at the same time, so if a select statement is the only one available we cannot just add a delete or insert to it.
Often applications include a way to send any SQL to the server. This is bad programming
practice, as it allows statements such as DDL to be executed.
PL/SQL Packages, Procedures and Functions
The final piece of the puzzle to talk about is packages, procedures and functions. It is possible
to call PL/SQL functions from SQL statements. The rules vary slightly with each version of
Oracle and indeed it was not possible to do so until PL/SQL version 2.1, which came with
Oracle RDBMS version 7.1. There are literally thousands of built-in functions and procedures
provided with the standard packages. These generally start with DBMS or UTL. The headers
can be found in $ORACLE_HOME/rdbms/admin.
Here is an example that calls a built in function supplied with Oracle. The function
(SYS.LOGIN_USER) in this case is quite simple and just returns the logged-in user, but it
illustrates the principle.
Newsletter: SQL Injection
Page 7
Click on the following URL
Now copy and paste one of the following strings to the Last Name field on the form
x' union select sys.login_user from sys.dual where 'x'='x
Both these display the Oracle User Name the Online Application uses.
The functions or procedures that can be called from SQL are quite limited: the function must
not alter the database state or package state if called remotely, and the function cannot alter
package variables if it is called in a where clause or group by clause. In versions earlier
than Oracle 8, very few built-in functions or procedures can be called from a PL/SQL function
that is called in SQL statements. The restrictions have been lifted somewhat from Oracle 8,
but users should not expect to be able to call file or output type packages such as UTL_FILE or
DBMS_OUTPUT or DBMS_LOB directly from SQL statements, as they must be executed in a
PL/SQL block or called by the execute command from SQL*Plus. It is possible to use many of
these procedures if they are part of a function that is written to be called from SQL.
To SQL inject and use PL/SQL packages, procedure or functions really requires a case of
dynamic PL/SQL. If a form or application builds and executes dynamic PL/SQL in the same
manner as described above, the same techniques can be used to insert calls to standard
PL/SQL packages on any PL/SQL packages or functions that exist in the schema.
If any database links exist from the database being attacked to any other database in the
organisation, those links can also be utilized in SQL injection attempts. This allows an attack
through the firewall to a database that is potentially not even accessible from the Internet!
Enumerating the Privileges
Access to SQL inject an Oracle database is great, but what would an attacker look for to gain
an advantage or a potential step up. He would, of course, need to enumerate the user he had
access to and see what that user can see and do. Given below are a few examples to give an
idea of what is possible.
The sample procedure above has been modified to select all 5 columns from our sample
customer table. If we use a union to extend an existing select statement then the new SQL
in the union must select the same number of columns and data types as the existing hijacked
select otherwise an error occurs, see the following:
Error messages leaking information
Now copy and paste one of the following strings to a field on the form
Newsletter: SQL Injection
Page 8
x' union select 1,'Y' from sys.dual where 'x'='x
(OR)
x' union select 1,'Y',1,1,1 from sys.dual where 'x'='x
The first string displays the following error
Error !! ORA-01789: query block has incorrect number of result columns
The second string displays the following error
Error !! ORA-01790: expression must have same datatype as corresponding
expression
The attacker can do trial and error guessing to eventually get the SQL statement correct,
which is given below.
x' union select 'Y','Y', 'Y','Y',1 from sys.dual where 'x'='x
If error messages are returned to the user either directly from the Oracle RDBMS or from the
application, then it is usually possible to work out where to change the SQL. An absence of
error messages makes it harder but not impossible.
Finding accessible objects
The attacker may first try to get the objects that the database user (in our sample site, the db
user WEBCUST) he is logged in as can see:
Click on the URL below
Now copy and paste the following string to the Last Name field on the form
x' union select object_name,subobject_name,object_type,'x',1 from user_objects where object_type='PACKAGE' and 'x'='x
This will display a list of database objects that the user can access !!
Get the Roles
Then he may try to get the roles that have been allocated directly to the user. Copy and paste
the following string to the Last Name field on the form
x' union select granted_role,admin_option,default_role,'x',1 from
user_role_privs where 'x'='x
Newsletter: SQL Injection
Page 9
This will display all system and application roles assigned to the database user he is logged in
as can see.
System Privileges
Then find out the system privileges that are granted directly to the user:
x' union select privilege,admin_option,'X','x',1 from user_sys_privs
where 'x'='x
Selecting from the table USER_TAB_PRIVS will give the privileges granted directly to the user
on objects. There are many system views that start USER_%, these show objects and
privileges that are granted to the current user as well as details about objects owned by the
user. For instance, there are 168 views or tables in Oracle 8.1.7, so this gives an indication of
the amount of detail that can be learned about the user you are logged in as. These USER_%
views do not include all the many privileges and options available to the current user;
however, besides those specifically granted, any user also can include all of the objects that
have permissions granted to PUBLIC.
PUBLIC is a catch-all that is available to all users in the Oracle database. There is a good set of
views (data dictionary views) , known as the ALL_% views, that is similar in construction to
the USER_% views. These include every item available to the current user, including PUBLIC
ones. A good place to start is the view ALL_OBJECTS, as it has a similar structure to
USER_OBJECTS and will display every object and its type available to the current user.
The V$ views is also a good set of views, provided they are available to the user. These give
information about the current instance, performance, parameters, and the like. V$PARAMETER
gives all of the database instance initialization parameters, including details of the UTL_FILE
directories. V$PROCESS and V$SESSION are another pair of views that will give details of
current sessions and processes. These will tell the user who is logged on, where they are
logged in from, and what program they are using, etc.
An example is given below
x' union select instance_name,host_name,version,'x',1 from v$instance
where 'x'='x
Having knowledge of Oracle and of the schema of the user being used is also a great
advantage. Quite obviously, some of this knowledge is not hard to learn, so the lesson is that
in case anyone is able to SQL inject into your database then you need to minimize what they
can do, see, or access.
Newsletter: SQL Injection
Page 10
Prevention of SQL Injection
On the surface, protection against SQL injection appears to be easy to implement but, in fact,
it is not as easy as it looks. The solutions fall into two distinct areas:
If possible, do not use dynamic PL/SQL. The potential for damage is much greater for
dynamic SQL, as there is scope to execute any SQL, DDL, PL/SQL etc.
If dynamic PL/SQL is necessary then use bind variables.
Do not allow dynamic SQL that uses concatenation, or at least filter the input values
and check for special characters such as quote symbols.
If concatenation is necessary then use numeric values for the concatenation part. This
way strings cannot be passed in to add SQL.
If concatenation is necessary then check the input for malicious code, e.g. check for
the word “union” in the string passed in or metacharacters such as quotes.
Use the principle of least privilege and ensure that the users created for the
applications have the privileges needed and all extra privileges (such as PUBLIC ones)
are not available.
Review the application source code. The code can be written in many different
languages, such as PHP, JSP, java, PL/SQL VB, etc., so the solutions vary. However,
they all follow a similar pattern. Review the source code for dynamic SQL where
concatenation is used. Find the call that parses the SQL or executes it. Check back to
where values are entered. Ensure that input values are validated and that quotes are
matched and metacharacters are checked. Reviewing source code is a task that is
specific to the language used.
Secure the database and ensure that all excess privileges are revoked.
If PL/SQL is used use AUTHID CURRENT_USER so that the PL/SQL runs as the logged
in user and not the creator of the procedure, function or package.
Filter out character like single quote, double quote, slash, back slash, semi colon,
extended character like NULL, carry return, new line, etc, in all strings from:
- Input from users
- Parameters from URL
- Values from cookie
For numeric value, convert it to an integer before parsing it into SQL statement
Here is another URL with the same purpose as the previous URLs (i.e. query the customer
table), but without the SQL Injection Vulnerability.
Here the length of Input field is limited to 30 (which is the length of the database column
last_name in the database) and the input string is checked for the presence of special
characters.
Try all the above examples on this form, you’ll find that you are unable to inject any useful
code.
Newsletter: SQL Injection
Page 11
Eg: x' union select username from all_users where '1'='1
Some more pointers:
Encrypt sensitive data so that it cannot be viewed.
Revoke all PUBLIC privileges where possible from the database
Remove unnecessary database users/accounts
Remove all sample databases if exists
Do not allow access to UTL_FILE, DBMS_LOB, DBMS_PIPE, DBMS_OUTPUT,
UTL_HTTP,UTL_SMTP or any other standard or application packages that allow access
to the O/S.
Change database default passwords.
Verify the patch level of the database.
Run the listener as a non-privileged user.
Ensure that minimum privileges are granted to application users.
Restrict PL/SQL packages that can be accessed from apache.
Remove all example scripts and programs from the Oracle install.
Set the appserver properties so that informative technical error messages are not
displayed to Web Users.
Again, SQL injection is a relatively simple technique and on the surface protecting against it
should be fairly simple; however, auditing all of the source code and protecting dynamic input
is not trivial, neither is reducing the permissions of all applications users in the database itself.
Be vigilant, grant what is needed, and try and reduce dynamic SQL to the minimum.
Detecting SQL Injection
Oracle is a large product and is applied in many diverse uses, so to say that SQL injection can
be detected would be wrong; however, in some cases, it should be possible for the DBA or
security admin to spot whether or not this technique is being used. If abuse is thought to be
taking place then forensic investigations can be done using the redo logs. A GUI tool called
Log Miner is available from Oracle to allow the redo logs to be analyzed. However, this has
serious restrictions: until version 9i, select statements could not be retrieved. The redo logs
allow Oracle to replay all of the events that altered data in the database; this is part of the
recovery functionality. It is possible to see all statements and data that have been altered.
Two PL/SQL standard packages, DBMS_LOGMNR and DBMS_LOGMNR_D, are available; these
packages allow the redo logs to be queried from the command line for all statements
processed.
Least Privilege
The extensive Oracle audit functionality can be utilized but, again, unless you know what you
are looking for, finding evidence of SQL injection taking place could like finding a needle in a
haystack. The principle of least privilege should be observed in any Oracle database so that
only those privileges that are actually needed are granted to the application database users.
This simplifies (minimizes) what can be legally done and, as a result, makes any actions
Newsletter: SQL Injection
Page 12
outside the scope of these users easier to spot. For instance, if the application user should
have access to seven tables and three procedures and nothing else, then using Oracle audit to
record select failures on all other tables would enable an administrator to spot any attempted
access to any table outside the applications realm.
A simple script can be built to generate the audit statements for the tables needed. There
should be no real performance issues with this audit, as no other tables should be accessed by
the application. As a result, it should not therefore generate audit. Of course, if someone
successfully accesses a table outside the realm, it would not be captured. This is merely
intended as a first step.
The same audit principles can be used to audit DDL, inserts and update failures or successes
Another idea could be to watch the SQL executed and look for any dodgy SQL. A job can be
scheduled on a regular basis to return the SQL statements in the SGA and then the SQL that is
returned can be used to guess if any SQL injection has been attempted. It is virtually
impossible to know all legal pieces of SQL an application generates; therefore, the same
applies to spotting illegal ones. A good first step would be to identify all statements with
“union” included or or statements with ‘x’=’x’ type lines. There could be performance issues
with extracting all of the SQL from the SGA regularly!
The best cure of course is prevention!
References:
http://www.nextgenss.com
http://www.securityfocus.com
http://www.petefinnigan.com
http://www.securiteam.com