12
2004 Smitha Padmanabhan [SQL INJECTION] An overview of SQL Injection in Oracle based applications and prevention techniques

SQL Injection - Newsletter

Embed Size (px)

Citation preview

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