I was playing a bit with FuzzOr and trying out different Oracle built-in schemas on 11g when I stumbled across something interesting in the parameters for MDSYS.SDO_JOIN. This caused FuzzOr to fail in fuzzing the function so I took a closer look.

SYS> select argument_name, type_owner, type_name, position, sequence from all_arguments where object_name = ‘SDO_JOIN’;

ARGUMENT_NAME         TYPE_OWNER     TYPE_NAME         POSITION SEQUENCE
--------------------- -------------- ----------------- -------- --------
TABLE2_PARTITION                                              8       10
TABLE1_PARTITION                                              7        9
PRESERVE_JOIN_ORDER                                           6        8
PARAMS                                                        5        7
COLUMN_NAME2                                                  4        6
TABLE_NAME2                                                   3        5
COLUMN_NAME1                                                  2        4
TABLE_NAME1                                                   1        3
                      MDSYS          SDO_ROWIDPAIR            1        2
                      MDSYS          SDO_ROWIDSET             0        1
10 rows selected.

So, do you notice anything weird here? SDO_ROWIDPAIR is listed as a parameter in the same position as TABLE_NAME1 but has no parameter name. Interesting. Initially, I thought that there might be something wrong with the view all_arguments but querying directly the argument$ table produced the same results.

Describing the function did not mention SDO_ROWIDPAIR at all:

SYS> desc MDSYS.SDO_JOIN
FUNCTION MDSYS.SDO_JOIN RETURNS SDO_ROWIDSET
 Argument Name                  Type           In/Out  Default?
 ------------------------------ -------------- ------- --------
 TABLE_NAME1                    VARCHAR2       IN
 COLUMN_NAME1                   VARCHAR2       IN
 TABLE_NAME2                    VARCHAR2       IN
 COLUMN_NAME2                   VARCHAR2       IN
 PARAMS                         VARCHAR2       IN      DEFAULT
 PRESERVE_JOIN_ORDER            NUMBER         IN      DEFAULT
 TABLE1_PARTITION               VARCHAR2       IN      DEFAULT
 TABLE2_PARTITION               VARCHAR2       IN      DEFAULT

The source code is wrapped but the header is:

FUNCTION SDO_Join (TABLE_NAME1 VARCHAR2, COLUMN_NAME1 VARCHAR2,
TABLE_NAME2 VARCHAR2, COLUMN_NAME2 VARCHAR2,
PARAMS VARCHAR2 DEFAULT NULL,
PRESERVE_JOIN_ORDER NUMBER DEFAULT 0,
TABLE1_PARTITION VARCHAR2 DEFAULT NULL,
TABLE2_PARTITION VARCHAR2 DEFAULT NULL)
RETURN MDSYS.SDO_ROWIDSET
AUTHID CURRENT_USER
PIPELINED IS

As you see, no mention of SDO_ROWIDPAIR which is in-fact mentioned later in the function as a declared local variable TAB_REC.

Anyway, this function is declared as AUTHID CURRENT_USER so even if can be injected (which I suspect that it can) it will not benefit the attacker.

Still, it’s an interesting case where the arguments table does not reflect the actual code and I suspect that there is a bug in populating this table.

Have you encountered similar cases?