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?