Happy New Year everyone!

As promised, in this blog post I will deal with the PL/SQL fuzzer I’ve created in my spare time and during flights. The goal for creating it was to provide an easy tool for the DBA to test PL/SQL code inside the database. This tested code can be internally developed or by a 3rd party. Before describing the architecture of the fuzzer and showing examples, I would like to make the following clarifications / warnings:

  • Fuzzing on production is a BIG no-no.  Never run the fuzzer on any database you care about. Always use test copies because running the fuzzer may crash / corrupt the database.
  • The fuzzer cannot guaranty that the code is not vulnerable, it can only try and find existing vulnerabilities. Running the fuzzer on a procedure and receiving a clean result does not mean that this procedure is free of vulnerabilities because the fuzzor does not analyze the code and does not visit all the code paths.
  • The fuzzer is in no way shape or form a finished product. It will blow in your face. It will fail when running your code. It contains multiple bugs. USE RESPONSIBLY!!!

Now that the warnings part is over, let’s talk about the design.
I chose PL/SQL for the following reasons:

  • Easy to run SQL statements
  • Built-in the database
  • Cross platform
  • Good enough for the task
  • DBAs already speak it fluently
  • Can be easily scheduled as a DB job from inside the database

The design is fairly simple and is based on the following requirements:

  • Must use database tables to track executions across invocations and to change various fuzzing parameters
  • Must try and find interesting (dynamic) code using discovery
  • Must easily generate reports on the fuzzing results

Here is the simple ERD:

ERD

ERD

The main tables are:

  • FUZZ_RUN – holds runs (invocations) of the fuzzor
  • FUZZED_OBJ – holds the list of objects for each run
  • FUZZED_EXEC – for each object, holds the executions (combination of parameters)
  • FUZZED_EXEC_PARAMS – holds the parameteres for each execution

Now that we are familiar with the main tables, let’s show an example:
(Please see the actual code and internal documentation for description of available methods and options.)

==========================================================================================

SYS> CREATE USER fuzz IDENTIFIED BY fuzz DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;

User created.

SYS> GRANT create session, create table, create sequence, create procedure, execute any procedure TO fuzz;

Grant succeeded.

SYS> alter user fuzz quota 200m on users;

User altered.

SYS> conn fuzz/fuzz
Connected.
FUZZ> set serveroutput on
FUZZ> @fuzzor

Package created.

Package body created.

FUZZ> exec fuzzor.create_fuzz_tables

PL/SQL procedure successfully completed.

FUZZ> exec fuzzor.run_package(‘Test of dbms_defer_sys’, ‘SYS’, ‘DBMS_DEFER_SYS’)

PL/SQL procedure successfully completed.

FUZZ> exec fuzzor.report(‘%defer%’)
Results for run Test of dbms_defer_sys with ID 1 started at 05/JAN/2009 11:27:25
and ended at 05/JAN/2009 11:27:25
Total number of fuzzed objects is: 27
Total number of executions is: 183
Total number of vulnerable objects is: 1
Results for DBMS_DEFER_SYS(ADD_DEFAULT_DEST)
The test started at 05/JAN/2009 11:27:26 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(DELETE_DEFAULT_DEST)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(PUSH)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE_ERROR)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE_ERROR_AS_USER)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(DELETE_TRAN)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= Y
Inputs of interest are:
Execution number: 51
Param1 = ‘)
Execution number: 53
Param1 = xxx’yyy
Results for DBMS_DEFER_SYS(DELETE_ERROR)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(SCHEDULE_EXECUTION)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(SCHEDULE_EXECUTION)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(SCHEDULE_PUSH)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:27 and vul
= N
Results for DBMS_DEFER_SYS(UNSCHEDULE_EXECUTION)
The test started at 05/JAN/2009 11:27:27 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(UNSCHEDULE_PUSH)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(DISABLED)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(SET_DISABLED)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(REGISTER_PROPAGATOR)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(UNREGISTER_PROPAGATOR)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(EXCLUDE_PUSH)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(DELETE_DEF_DESTINATION)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(PURGE)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(SCHEDULE_PURGE)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(CLEAR_PROP_STATISTICS)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(NULLIFY_TRANS_TO_DESTINATION)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE_ERROR_CALL_AS_USER)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(EXECUTE_ERROR_CALL)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N
Results for DBMS_DEFER_SYS(PUSH_WITH_CATCHUP)
The test started at 05/JAN/2009 11:27:28 and ended 05/JAN/2009 11:27:28 and vul
= N

PL/SQL procedure successfully completed.

==========================================================================================

As you can see from the above example, it is very easy to run on specific packages (or all source in a schema) and it can find vulnerabilities (even in built-in packages from Oracle).

Since you, my diligent blog reader, got this far, here is the fuzzer code in a single PL/SQL file. I would love to hear your comments and suggestions. If there is enough interest, I can create a sourceforge project to host this code and work on improvements with your help.

fuzzor